C指针和内存分配:Realloc数组和指针传递

对于那些有C经验的人来说,这将是一个简单的内存分配/引用问题:

这是我的数据结构:

struct configsection { char *name; unsigned int numopts; configoption *options; }; typedef struct configsection configsection; struct configfile { unsigned int numsections; configsection *sections; }; typedef struct configfile configfile; 

以下是初始化configsection或configfile以及将配置文件添加到配置文件的例程:

 // Initialize a configfile structure (0 sections) void init_file(configfile *cf) { cf = malloc(sizeof(configfile)); cf->numsections = 0; } // Initialize a configsection structure with a name (and 0 options) void init_sec(configsection *sec, char *name) { sec = malloc(sizeof(configsection)); sec->numopts = 0; sec->name = name; printf("%s\n", sec->name); } // Add a section to a configfile void add_sec(configfile *cf, configsection *sec) { // Increase the size indicator by 1 cf->numsections = cf->numsections + 1; // Reallocate the array to accommodate one more item cf->sections = realloc(cf->sections, sizeof(configsection)*cf->numsections); // Insert the new item cf->sections[cf->numsections] = *sec; } 

我相信我的问题源于我的init_sec()函数。 这是一个例子:

 int main(void) { // Initialize test configfile configfile *cf; init_file(cf); // Initialize test configsections configsection *testcs1; init_sec(testcs1, "Test Section 1"); // Try printing the value that should have just been stored printf("test name = %s\n", testcs1->name); 

虽然init_sec()printf()成功打印了我刚刚存储在init_sec()的名称,但是在printf()printf()中尝试相同的操作会产生分段错误。 此外, addsec()会产生分段错误。

这个例程应该是

 void init_file(configfile **cf) { *cf = malloc(sizeof(configfile)); (*cf)->numsections = 0; (*cf)->sections = NULL; // You forgot to initialise this. } 

即由init_file(&myconfigfilepointer);调用init_file(&myconfigfilepointer); 所以malloc返回值被传回。

需要为init_sec做同样的技巧

此function不正确 – 这是更正版本

 void add_sec(configfile *cf, configsection *sec) { // Increase the size indicator by 1 // Reallocate the array to accommodate one more item cf->sections = realloc(cf->sections, sizeof(configsection)*(1 + cf->numsections)); // Insert the new item cf->sections[cf->numsections] = *sec; // Since arrays start at 0 cf->numsections = cf->numsections + 1; } 

然后,您需要调整main的呼叫

在任何时候你都没有初始化cf->sections ,这意味着当你第一次尝试重新分配它时,你会传递垃圾。 添加:

  cf->sections = NULL; 

init_file应该有帮助。

你也没有检查任何返回代码,但你知道是吗?

您需要传递要更新的值的指针…例如:

 // Initialize a configfile structure (0 sections) void init_file(configfile **cf) { *cf = malloc(sizeof(configfile)); (*cf)->numsections = 0; } configfile *var; init_file(&var); printf("%d\n", var->numsections); 

否则,您只是更新本地指针* cf而不是原始传入的值

你需要真正重新思考如何在C中传递函数参数以及指针是什么。 您的问题与内存分配无关。 相反,您的代码只将一个指向动态分配内存的指针分配给一个局部变量 ,调用代码对此一无所知。

虽然您可以通过将指针传递给调用者的指针(即双指针)来解决问题,但这不一定是最优雅或最常用的处理方式。 相反,您应该从函数返回分配的结果。 当你在它时,你也应该使用calloc立即将内存清零。 把它全部包装起来:

 typedef struct substuff_ { int a; double b; } substuff; typedef struct stuff_ { unsigned int n; substuff * data; } stuff; substuff * init_substuff() { substuff * const p = malloc(sizeof *p); if (p) { p->a = 5; p->b = -0.5; } return p; } stuff * init_stuff() { substuff * const p = init_substuff(); if (!p) return NULL; stuff * const q = malloc(sizeof *q); if (q) { q->n = 10; q->data = p; } return q; } 

作为练习,您应该编写相应的函数void free_substuff(substuff *)void free_stuff(stuff *)

是的, init_sec存在问题

 // Initialize a configsection structure with a name (and 0 options) void init_sec(configsection *sec, char *name) { sec = malloc(sizeof(configsection)); sec->numopts = 0; sec->name = name; printf("%s\n", sec->name); } 

你只是在这里复制名称指针,这意味着它指向名称的原始存储。 如果你这样调用init_sec

 configsection foobar() { configsection sec; char name[80]; get_name(name); init_sec(sec, name); return sec; } 

foobar返回的那一刻, name指针变得无效。 您需要复制字符串并保留您的私人副本。 在init_sec

  sec->name = strdup(name); 

但还有更多。 在init_sec第一行中,您将使用malloc之一覆盖传递给init_sec的指针。 所以新指针永远不会传递回calle。 要么使用指向指针的指针,要么根本不采用configsection指针(毕竟,你要分配),但只返回已分配的指针:完成更正的function:

 // Initialize a configsection structure with a name (and 0 options) configsection* init_sec(char *name) { configsection *sec = malloc(sizeof(configsection)); sec->numopts = 0; sec->name = name; printf("%s\n", sec->name); return sec; }