Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C指针和内存分配:Realloc数组和指针传递_C_Pointers_Memory Management_Reference - Fatal编程技术网

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

C指针和内存分配:Realloc数组和指针传递,c,pointers,memory-management,reference,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 *

对于有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以及将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成功地打印了我刚才存储在configsection中的名称,但在main的printf中尝试相同的操作会产生分段错误。此外,addsec产生分段错误

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

// 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,而不是原始传入值

在任何时候都不初始化cf->sections,这意味着当您第一次尝试重新锁定它时,您传递的是垃圾。添加:

 cf->sections = NULL;
初始化文件应该有帮助

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

此例程应该是

void init_file(configfile **cf) { 
    *cf = malloc(sizeof(configfile)); 
    (*cf)->numsections = 0;
    (*cf)->sections = NULL; // You forgot to initialise this.
}
i、 e.由init_文件&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中的调用

是的,init_sec中存在问题

您只是在这里复制name指针,这意味着它指向name的原始存储。如果你这样叫init_sec

configsection foobar()
{
    configsection sec;
    char name[80];

    get_name(name);
    init_sec(sec, name);
    return sec;    
}
foobar返回时,名称指针变为无效。您需要复制字符串并保留您的私人副本。在init_sec中:

但还有更多。在init_sec的第一行中,您将用malloc的指针覆盖传递给init_sec的指针。因此,新指针永远不会传递回被调用方。或者使用指向指针的指针,根本不使用configsection指针毕竟,您正在分配,只需返回已分配的指针:Complete corrected 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;
}

您需要重新思考函数参数在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_substuffsubstuff*和void free_stuff*

@IntermediateHacker:谢谢。这有什么原因吗?嗯,如果你只是使用标准C,不是这样。但是有时候,使用GObject等,它可能会导致问题。。。到达那里*cf->numsections=0;生成一个非结构或联合错误。为答案添加了操作顺序,请尝试。此答案完全错误。您需要*cf->numsections=0或*cf.numsections=0-它们是等效的-而不是两者的组合。更新:我的错误-见下文。@Geoffrey:哦,是的!我以前见过!谢谢你。@Tim-我以为我已经修好了???这不是完全错误,这是语法错误,*cf.numsections无效,它是指向定义中指针的指针。呵呵,我也错过了这一个+1:添加了以下内容:*cf->sections,我认为这可能是解决方案。啊,是的。您注意到我错误地分配了数组值。杰出的是的,这似乎是正确的。如果我试图在初始化函数之外访问name值,那么我只会得到null。@thoughtadvances:对不起,我过早地单击了“回答”。你有两个问题。一个是不重复的名称字符串,另一个是分配内存的字符串,但从不传回指针。我发现在双指针情况下很难跟踪指向的内容。我将尝试实现这一点。
// 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;
}
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;
}