【问题标题】:learn c the hard way chapter heap and stack code学习c的艰辛方式章节堆和堆栈代码
【发布时间】:2013-10-13 03:01:06
【问题描述】:

在 Zed 的流行(观点)系列中,在“堆和堆栈”一章中,数据库的代码如下

请注意这是 Zed Shaw 的代码

struct Address {
    int id;
    int set;
    char name[MAX_DATA];
    char email[MAX_DATA];
};

struct Database {
    struct Address rows[MAX_ROWS];
};

struct Connection {
    FILE *file;
    struct Database *db;
};




struct Connection *Database_open(const char *filename, char mode)
{
    struct Connection *conn = malloc(sizeof(struct Connection));
    if(!conn) die("Memory error");

    conn->db = malloc(sizeof(struct Database));
    if(!conn->db) die("Memory error");

    if(mode == 'c') {
        conn->file = fopen(filename, "w");
    } else {
        conn->file = fopen(filename, "r+");

        if(conn->file) {
            Database_load(conn);
        }
    }

    if(!conn->file) die("Failed to open the file");

    return conn;
}



void Database_create(struct Connection *conn)
{
    int i = 0;

    for(i = 0; i < MAX_ROWS; i++) {
        // make a prototype to initialize it
        struct Address addr = {.id = i, .set = 0};
        // then just assign it
        conn->db->rows[i] = addr;
    }
}

我觉得在他的 Database_create 函数中,他调用了 struct Address 形式的分配内存,而内存 f 已经分配给创建 struct database ,有点奇怪。

然后我通过这种思路推断出他两次调用 malloc 的事实,首先分配堆内存用于创建 Connection,然后再次分配用于在结构 Connection(即 Databse)中创建结构类型也很奇怪..我推断可能 Zed 知道并理解结构嵌套必须逐层构建。

就在此处发布问题之前,我决定编写一个简单的嵌套结构类型,并尝试通过一个 malloc 调用创建的最外层结构访问结构层内的数据....我的理由是,如果我认为没有必要逐层构造嵌套结构是真的,我可以访问嵌套数据而不会出现分段错误。我做到了

代码如下

#include<stdlib.h>
#include<stdio.h>




struct Killfly{

    char str[20];

};

struct wtf
{
    struct Killfly a;   
};

struct wtf2{

    struct wtf k;
};


int main(){
    struct wtf2*fly=malloc(sizeof(struct wtf2));
    printf("size of %ld \n",sizeof(*fly));
    fly->k.a.str[0]='a';
    //printf("size of wtf is %ld \n",sizeof(wtf));
    free(fly);

    return 0;

}

并且它在没有段错误的情况下写入

问题

那么为什么 Zed 放置多个 malloc 调用,以及为什么当他已经为结构数据库分配空间时,在函数 Database_struct 中,在 for 循环中,他继续调用基于堆栈的 struct Address 对象并将它们放入数组中上述类型?

【问题讨论】:

  • “那么为什么 Zed 会发出多个 malloc 调用” - 他在考验我对人性的信心
  • @EdHeal 通过那句话,你的意思是有一个明显的答案,我的思路是错误的?
  • 因为他想要更多的堆栈内存(这就是malloc的目的)
  • Zed 不是在低俗小说中被杀的吗?
  • 您有真正的问题需要帮助吗?

标签: c struct malloc


【解决方案1】:

Database_open() 中有多个 malloc 调用,因为 struct Connection 包含指向 struct Database 的指针,而不是直接合并 struct Database。本来可以这样做的:

struct Connection {
    FILE *file;
    struct Database db;     // directly incorporate a `struct Database`
};

实际上,这就是您在 struct wtf2 示例中所做的。有一些设计决策可以做到这一点,因此由于各种原因,一种方法可能比另一种更好。我不熟悉“Learn C the Hard Way”系列,所以我无法评论设计选择是否讨论得很好。

至于使用基于栈的Address对象来初始化数组,这是C的对象初始化的一个方便,在评论中提到了做原型:

    // make a prototype to initialize it
    struct Address addr = {.id = i, .set = 0};

在 C 中,没有可以直接分配给 conn-&gt;db-&gt;rows[i] 的结构字面量之类的东西。但是在struct object的声明中,可以提供一个初始化器来初始化该对象。这就是这里发生的事情——struct Address 对象的声明仅用于提供能够指定初始化程序的便利,然后该对象立即分配给堆分配的结构(这是我们真正想要初始化的)。代码序列或多或少相当于:

    memset( &conn->db->rows[i], 0, sizeof(conn->db->rows[i]));
    conn->db->rows[i].id = i;

【讨论】:

  • 我的错,我忽略了 Connection 结构中的指针。
猜你喜欢
  • 2012-12-24
  • 2013-05-16
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
  • 2014-08-12
  • 2010-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多