【问题标题】:C - What is wrong with my memory freeing function?C - 我的内存释放功能有什么问题?
【发布时间】:2015-05-15 02:58:01
【问题描述】:

我有一个结构,它包含 2 个整数和一个指向另一个结构的指针。我首先为结构分配内存,然后为指针分配内存。当我释放内存时,我先释放指针,然后释放结构。

当我运行我的程序并调用释放内存的函数时,它会在调用时崩溃。当我不调用释放内存的函数时,它工作正常,但是我没有释放内存。

我尝试删除释放分配给指针的内存并且程序不会崩溃的行,但我认为这是不对的,因为每个“malloc/calloc”都需要一个“free”,对吗?有人看到释放功能有什么问题吗?

//Define a struct data type
struct q_element
{
    //Declaration of struct members
    int element;
    int priority;
    struct q_element *next_element;
};

//Method to allocate memory
struct q_element* allocateStruct()
{
    //Declaration of a variable
    struct q_element *e;

    //Allocate memory for one queue element
    e = malloc(sizeof(struct q_element));

    //Allocate memory for one pointer to a queue element
    e->next_element = calloc(1,sizeof(struct q_element*));

    //Initialize integer members of queue element
    e->element = 0;
    e->priority = 0;

    return e;
}

//Method to free memory allocated
void freeStruct(struct q_element* e)
{
    //Free up pointer member
    free(e->next_element);

    //Free up struct
    free(e);
}

【问题讨论】:

  • 我相信您的意思是在e->next_element 上递归应用freeStruct 而不是free(但它应该是尾递归)。
  • 您确定在释放后不使用释放的内存吗?但是您的结构可疑地类似于某些链表(队列?)项目,在这些项目中,这种分配释放可能会成为问题的根源。
  • e->next_element = calloc(1,sizeof(struct q_element*)); --> e->next_element = NULL; , free(e->next_element);free(e); --> if(e){freeStruct(e->next_element);free(e);}
  • 如果你只释放一个结构,函数本身并没有错。但是我的猜测是这些是用来组成一个列表的,而你释放整个列表的代码是错误的,但由于它不在这里,我们看不到它。
  • 是的,它用于优先级 q 队列,每当我弹出队列中最高优先级的元素时,我都会调用 freeStruct 函数以释放弹出元素占用的内存。我只释放一个一次,而不是一个 for 循环中的整个列表@LeeDanielCrocker

标签: c pointers memory-management struct free


【解决方案1】:

您不需要为next_element 指针分配内存。指针已经存在,就像int element 一样。

所以如果你只想分配一个元素,你可以将next_element指针设置为NULL,一切都很好。

【讨论】:

  • 确实,只有当您有 另一个 结构要链接时,您才为 next_element 设置一个值。
  • ...因为如果您现在为下一个struct 分配内存,那么您会遇到问题:that struct 中的next_element 会做什么,等等。
  • 所以我不需要为指针分配内存,因此不需要在之后释放它?那么在为结构分配内存时需要进一步分配哪些数据类型?我记得当我有一个带有字符串的结构时,我还必须为字符串分配内存。整数和指针不需要,字符串需要,还有什么?
  • 是的,你不需要为指针分配内存,也不需要释放它。所有“静态分配”的东西,比如something mything;,都不需要free,所有“动态分配”的东西,比如something *mything = malloc(...,都需要free
  • 几乎在所有情况下,您都可以选择是静态分配还是动态分配。 int arr[20]; 是静态分配的数组,int* arr = malloc(20*sizeof(int)); 是动态分配的数组。
【解决方案2】:

您没有为该行中的e->next_element 分配足够的内存:

e->next_element = calloc(1,sizeof(struct q_element*));
                                             //  ^^^ remove the *

应该是:

e->next_element = calloc(1,sizeof(struct q_element));

如果你使用e->next_element 就好像它是一个有效的指针,你很可能最终访问了你没有分配的内存。这破坏了calloc 创建的一些簿记信息,当您调用free 时会导致问题。

【讨论】:

  • 我只想为指向结构的指针分配内存,而不是整个结构
  • @Yiannis,struct 已经有了指针。指针可以为 NULL 或需要指向 struct。只为指针分配内存并将其分配给e->next_element 是没有意义的。
【解决方案3】:

//Allocate memory for one pointer to a queue element
e->next_element = calloc(1,sizeof(struct q_element*));

您为指向 q_element 结构的指针分配空间,而不是 q_element 结构。您是否尝试写入此结构,因为如果是这样,那可能就是出错的地方。

顺便说一句,你最好还是这样做

e->next_element = 0

allocate_struct 内部,稍后在函数外部执行e->next_element = allocate_struct()

【讨论】:

    【解决方案4】:

    除了其他人都提到的分配之外,您还需要一个哨兵来检查下一个元素是否已经被释放。您可能正在尝试双重免费。

    试试下面的代码:

    void freeStruct(struct q_element* e)
    {
        //Free up pointer member
        if(e->next_element != 0){
            free(e->next_element);
            e->next_element = 0;
        }
    
        //Free up struct
        free(e);
    }
    

    【讨论】:

    • 使用空指针调用free 什么都不做,而且非常安全。
    • @alain:是的,但是在free之后,指针不保证指向NULL。因此,虽然if 是不必要的,但在我看来,e->next_element = NULL; 仍然是一个好主意。
    • 我一次只会释放一个 q_element,每个 pop 一个
    • 是的,将释放的指针设置为NULL 是个好主意,并且可以使代码更安全。
    • 我的意思是:一般是个好主意,但是这里设置e->next_element = NULL;没有意义,因为e也被释放了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多