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

时间:2012-02-25 11:34:42

标签: c pointers memory-management reference

对于那些有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()会产生分段错误。

5 个答案:

答案 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 *)

相关问题