【问题标题】:"double free or corruption" - free memory on array of structs - C“双重释放或损坏” - 结构数组上的释放内存 - C
【发布时间】:2021-08-26 20:46:18
【问题描述】:

我是 C 的新手,必须在大学使用它,并且在 atm 上真的很挣扎。

我们得到了一些代码,并且必须在其中编写一些函数,以便它们与我们得到的东西一起工作。

我的代码:

int readData(char *path, linkedList *list, meal **menu) {
/* --- Config --- */

int ctr=0;                      //to count parsed lines
int linesCount=1;               //to count lines in file first
char ch;                        //char to check while counting lines
FILE *fp = fopen(path, "r");    //file to read from
FILE *fp2 = fopen(path, "r");    //file to read from
char chunk[128];                //buffer for each line
customerParty *newCustomer;

/* --- Code --- */

//count lines to malloc enough memory afterwards
while((ch=fgetc(fp2))!=EOF) {
    if(ch=='\n')
        linesCount++;
}

//allocate memory
newCustomer = malloc(linesCount * sizeof(customerParty));

//read file line by line, initialize a newCustomer out of each line
while(fgets(chunk, sizeof(chunk), fp) != NULL) {
    parseLine(chunk, &newCustomer[ctr], menu);
    listInsert(list, &newCustomer[ctr]);
    ctr++;
}

//close files
fclose(fp2);
fclose(fp);

return ctr;}

并且提供的代码/类执行此操作(缩短)

void listRemove(linkedList *list, customerParty *elem) {

{...} 

elem->next = NULL;

free(elem->name);
free(elem->order);
free(elem);}

从 gdb 我知道 free(elem->order) 不是问题,而是 free(elem),但为什么会这样呢?为什么它不能释放我分配的内存? 我总是收到“双重释放或损坏(输出)”错误。

非常感谢您的帮助!谢谢!

#edit:感谢您的帮助!

我的代码应该做什么?

  • 获取一个文件并为该文件中的每一行创建一个 newCustomer
  • 在每个 newCustomer 上调用 parseLine 函数(只是用每一行的信息填充结构)
  • 调用 listInsert 函数将其添加到列表中

我不允许更改 listRemove 函数中的任何内容,他们特别说我们应该对其进行编程,以便他们的代码可以正确释放内存。目前,我的代码创建了 newCustomer 结构并将它们完美地填充到列表中,但最后的释放是问题所在。 这是我唯一使用 malloc 的地方,我只是想创建一个包含 N 个 customerParty 的数组来填充它们。

【问题讨论】:

  • 我们需要足够的代码来复制问题。我们看不到这些东西是如何分配的,因此无法判断它们是否被正确释放。
  • 给定char ch(ch=fgetc(fp2))!=EOF 无法可靠地检测到文件结束,因为EOF 是一个整数值,它可以' t 适合 char
  • 为了帮助分配内存,所有malloc()free() 相关的代码都应该出现在问题中。您的问题包含更多 free 调用,malloc 调用,这至少是可疑的。

标签: c linked-list malloc dynamic-memory-allocation free


【解决方案1】:

如果我在这句话中理解正确

newCustomer = malloc(linesCount * sizeof(customerParty));

您分配了一个linesCount 元素数组(列表的节点),然后将指向每个元素的指针传递给函数listInsert

listInsert(list, &newCustomer[ctr]);

因此您不能删除已分配数组的单个元素您只能删除整个数组。否则,当您免费调用时,您会出现未定义的行为。

您需要分别动态创建列表的每个节点,并将指向动态分配节点的指针传递给函数listInsert

【讨论】:

  • 我以为我是在动态创建它们 - 所以任务失败了。谢谢你的建议——我想这是有道理的!你有一个如何动态创建结构的例子吗?我真的不知道我要搜索什么 - 我有 atm 是我搜索时发现的。
  • @xEnemyy 在 SO 有很多创建链表的例子。例如,到目前为止,我回答了一个与链表相关的问题stackoverflow.com/questions/67909681/…
【解决方案2】:

从您的代码中,我宁愿认为您想要的是数组,而不是链表。

customerList *add(customerList *customerArray, customerParty *customer)
{
    size_t newSize = customerArray ? customerArray -> size + 1 : 1;
    customerArray = realloc(customerArray, sizeof(*customerArray) + newSize * sizeof(customerArray -> customers[0]));
    if(customerArray)
    {
        customerArray -> size = newSize;
        memcpy(&customerArray -> customers[newsize - 1], customer, sizeof(*customer));
    }
    return customerArray;
}

customerList *removeAtPos(customerList *customerArray, size_t pos)
{
    if(customerArray && customerArray -> size > pos)
    {        
        memmove(&customerArray -> customers[pos], &customerArray -> customers[pos + 1], (customerArray -> size - pos - 1) * sizeof(customerArray -> customers[0]));
        if(customerArray -> size = 1) 
        {
            free(customerArray);
            customerArray = NULL;
        }
        else
        {
            customerArray = realloc(customerArray, sizeof(*customerArray) + (customerArray -> size - 1) * sizeof(customerArray -> customers[0]));
    }
    return customerArray;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    相关资源
    最近更新 更多