释放结构数组

时间:2014-10-06 17:48:40

标签: c memory struct free alloc

我做过一些研究,但无法找到问题的答案。

我在解放我的结构时遇到了问题。

这是我创建结构的方式:

struct Structure * newStructure(int N) 
{
    struct Structure * structure;
    int i;
    structure = (struct Structure * ) malloc(N * sizeof(struct Structure));
    for (i = 0; i < N; i++) 
    {
        structure[i].i_Number = (int * ) malloc(sizeof(int));
        structure[i].c_Char = (char * ) malloc(sizeof(char));
        structure[i].c_Char[0] = '\0';
        structure[i].d_Float = (double * ) malloc(sizeof(double));
    }
    return structure;
}

一切都在这一点上起作用。之后我用随机值填充每个变量,使它们不为空。

我这样调用我的freeMemory函数freeMemory(structure, amountOfStructures); 这里是freeMemory函数本身:

void freeMemory (struct Structure* structure, int N)
{
    int i;

    for( i=0 ; i<N ; i++ )
    {
        if (structure[i].i_Number!=NULL) free(structure[i].i_Number);
        if (structure[i].c_Char!=NULL) free(structure[i].c_Char);
        if (structure[i].d_Float!=NULL) free(structure[i].d_Float);
    }

    free(structure);
}

免费(结构)部分工作正常。但是for循环存在问题,我不知道我在这里做错了什么。

@EDIT 我正在添加我的结构声明:

struct Structure{
    int *i_Number;
    char *c_Char;
    double *d_Float;
};

@ EDIT2 这是初始化struct的函数:

    struct Structure* randomizing (int N)
{
    struct Structure* structure = newStructure(N); int i;
    srand(time(NULL));

    for (i = 0; i < N; i++)
    {
        int _i; char _c; double _d;

         _i = rand()%1000000;
         _c = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" [rand () % 26];
         _d = 0;

        setStructureNumber(structure, i,(int*) _i);
        setStructureChar(structure, i, (char*) _c);
        setStructureDouble(structure, i, &_d);

//我已经评论过上面的MUTATORS并且错误没有显示出任何错误,因此有些错误

    }

    return structure;
    }

我称之为:

    struct Structure* structure;
    structure = randomizing(amountOfStructures);

使用的变异器:

// Mutators
void setStructureNumber (struct Structure* structure, int p, int* num)
{
    if (structure[p].i_Number != NULL) free(structure[p].i_Number);

    structure[p].i_Number = (int*) malloc (sizeof(int));
    structure[p].i_Number = num;
}

void setStructureChar (struct Structure* structure, int p, char* str)
{
    if (structure[p].c_Char != NULL) free(structure[p].c_Char);

    structure[p].c_Char = (char*) malloc (sizeof(char));
    structure[p].c_Char = str;
}

void setStructureDouble (struct Structure* structure, int p, double* dou)
{
    if (structure[p].d_Float != NULL) free(structure[p].d_Float);

    structure[p].d_Float = (double*) malloc (sizeof(double));
    structure[p].d_Float = dou;
}

3 个答案:

答案 0 :(得分:2)

最可能的原因是代码中的某个地方超出了您分配的内存范围,从而破坏了堆的完整性。这种未定义行为经常遇到的实际表现是free失败,当库检测到堆的问题时。

在您的分配周期内,您只为结构对象的每个字段分配每个相应类型的一个对象。例如,您只为c_Char字段分配一个字符,并使用\0对其进行初始化。这可能表明c_Char旨在保存字符串(是吗?)。如果是这样,那么您分配的内存仅足以用于空字符串。如果以后不重新分配该内存,则将更长的字符串放入该内存的任何尝试都将破坏堆的完整性并触发未定义的行为。

这同样适用于其他领域。但是,如果没有您的额外解释,则无法确定它是对还是错。至少,您必须提供struct Structure的定义。你必须解释你的意图。为什么要为struct字段动态分配单对象内存而不是仅仅使这些对象成为struct的直接成员?


您发布的其他代码完全彻底破解。

首先,你将你的mutators称为

setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);
setStructureDouble(structure, i, &_d);

这没有任何意义。为什么要尝试将整数值_i转换为指针类型???如果您想获得指向_i的指针,则会以&_i完成。您已在最后一次通话中正确执行此操作,您将通过&_d。为什么前两个呼叫与上一个呼叫不同?你背后的逻辑是什么?

其次,在你的mutator函数里面

void setStructureNumber (struct Structure* structure, int p, int* num)
{
    if (structure[p].i_Number != NULL) free(structure[p].i_Number);

    structure[p].i_Number = (int*) malloc (sizeof(int));
    structure[p].i_Number = num;
}

你正在释放旧内存并分配新内存。为什么?为什么不重复使用旧内存来存储新值? (顺便说一下,在调用free之前,没有必要检查指针是否为空,因为free无论如何都会在内部检查它。)

第三,在分配新内存后,你会立即通过覆盖malloc返回的指针值来泄漏它,并使用从外部传递的指针值

structure[p].i_Number = num;

同样,这没有任何意义。这实际上是导致free崩溃的原因 - 从外部传递的指针要么是无意义的随机值(如(int *) _i(char *) _c)),要么指向局部变量(如你的&_d)。


没有办法&#34;纠正&#34;您的代码在不知道您首先尝试做什么的情况下。有太多完全不必要的内存分配和重新分配以及其他不合逻辑的东西。我只需将mutator函数重写为

void setStructureNumber (struct Structure* structure, int p, int num)
{
    *structure[p].i_Number = num;
}

注意 - 没有内存重新分配,参数按值传递。

这些功能将被称为

setStructureNumber(structure, i, _i);
setStructureChar(structure, i, _c);
setStructureDouble(structure, i, _d);

但同样,这与你所拥有的完全不同,我不知道这是否是你所需要的。

答案 1 :(得分:1)

从技术上讲,你正在做的事情没有错(除了在调用malloc之前缺少对分配的错误检查,NULL结果的不必要的强制转换以及不必要的free检查。

这应该可以正常工作,假设您传递了正确的N值,并且您不会多次释放内容:

struct Structure * newStructure(int N) {
    struct Structure * structure = malloc(N * sizeof(struct Structure));
    for (int i = 0; i < N; i++) {
        structure[i].i_Number = malloc(sizeof(int));
        structure[i].c_Char = malloc(sizeof(char));
        structure[i].c_Char[0] = '\0';
        structure[i].d_Float = malloc(sizeof(double));
    }
    return structure;
}

void freeMemory (struct Structure* structure, int N)
{
    for(int i=0 ; i<N ; i++ )
    {
        free(structure[i].i_Number);
        free(structure[i].c_Char);
        free(structure[i].d_Float);
    }
    free(structure);
}

您可以使用valgrind等内存诊断工具来确保不会多次释放内容。

答案 2 :(得分:0)

在你的mutators中你泄漏了内存,然后指向局部变量(我的评论)

void setStructureChar (struct Structure* structure, int p, char* str)
{
    if (structure[p].c_Char != NULL) free(structure[p].c_Char);

// allocates new memory and points c_Char at it.
    structure[p].c_Char = (char*) malloc (sizeof(char));

// makes c_Char point to where `str` is pointing; now the allocated memory is leaked
    structure[p].c_Char = str;
}

如果稍后在free上执行structure[p].c_Char,则会导致未定义的行为,因为您使用指向局部变量的指针调用此函数。如果您在释放它之前尝试访问c_Char,则可能在其他地方也有未定义的行为。

其他变异者也有同样的问题。

要将此更改structure[p].c_Char = str;“修复”为*structure[p].c_Char = *str;

你也有错误:

setStructureNumber(structure, i,(int*) _i);
setStructureChar(structure, i, (char*) _c);

分别表示&_i&_c。我建议您从代码中删除所有强制转换。充其量他们是多余的;在最坏的情况下(例如在这两行中),它​​们隐藏了编译器将诊断出的错误。

同样删除free之前的所有NULL检查,它们是多余的,使您的代码难以阅读。相反,在调用malloc之后执行NULL检查,如果malloc返回NULL,则中止程序。

然而,整个设置似乎是一个可怕的设计。你可以通过值将事物传递给mutators。并且您可以将结构更改为不包含指针,因此不需要所有这些额外的分配。