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 関数で、メモリ f が struct database の作成のためにすでに割り当てられているときに、彼がフォーム struct Address の割り当てられたメモリを呼び出すのは奇妙だと感じました。
そして、その考え方から、彼が malloc を 2 回呼び出したという事実を推論しました。最初は Connection の作成にヒープ メモリを割り当て、次に構造体 Connection 内の構造体型の作成 (つまり、Databse) は奇妙である必要があります。ええと..私は、おそらく Zed は、構造体の入れ子をレイヤーごとに構築する必要があることを知っていて理解していたと推論しました。
ここに質問を投稿する直前に、単純なネストされた構造体型を記述し、1 つの 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 ループで構造体 Database にスペースを既に割り当てているのに、スタック ベースの構造体 Address オブジェクトを呼び出して、それらを前述の型の配列に配置したのはなぜですか。 ?