对于那些有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);
尽管printf()
中的init_sec()
成功打印了我刚刚存储在配置部分中的名称,但在printf()
的{{1}}中尝试相同的操作会产生分段错误。此外,main()
会产生分段错误。
答案 0 :(得分:2)
在任何时候你都没有初始化cf->sections
,这意味着当你第一次尝试realloc
时,你就会传递垃圾。添加:
cf->sections = NULL;
到init_file
会有所帮助。
您也没有查看任何退货代码,但您知道是吗?
答案 1 :(得分:2)
此例程应为
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
(*cf)->sections = NULL; // You forgot to initialise this.
}
即。由init_file(&myconfigfilepointer);
调用,以便传回malloc
返回值。
需要为init_sec
此功能不正确 - 此处为更正版本
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
答案 2 :(得分:1)
您需要传递要更新的值的指针...例如:
// 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而不是原始传入的值
答案 3 :(得分:1)
是的,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;
}
name
指针在foobar
返回时失效。您需要复制字符串并保留您的私人副本。在init_sec
:
sec->name = strdup(name);
但还有更多。在init_sec
的第一行中,您将覆盖使用malloc传递给init_sec
的指针。所以新指针永远不会传递回calle。要么使用指向指针的指针,要么根本不采用configsection指针(毕竟,你要分配),但只返回已分配的指针:完成更正的功能:
// 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;
}
答案 4 :(得分:1)
你需要真正重新思考如何在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 *)
。