【问题标题】:Why double free or corruption error in C? I freed my mallocs为什么在 C 中出现双重释放或损坏错误?我释放了我的 malloc
【发布时间】:2017-09-30 03:29:13
【问题描述】:

我收到此错误:

`./sorter' 中的错误:双重释放或损坏 (!prev):0x0000000000685010

然后是一堆数字,这是内存映射。 我的程序从标准输入读取电影及其属性的 CSV 文件并将其标记化。带有逗号的电影标题用引号括起来,所以我将每一行分成 3 个标记,并使用逗号作为分隔符再次标记前后标记。我在代码末尾释放了所有的 malloc,但仍然出现此错误。 csv 被扫描到最后,但我收到一条错误消息。如果我根本不释放 malloc,我不会收到错误消息,但我非常怀疑它是否正确。这是我的 main() :

char* CSV = (char*)malloc(sizeof(char)*500);
char* fronttoken = (char*)malloc(sizeof(char)*500);
char* token = (char*)malloc(sizeof(char)*500);
char* backtoken = (char*)malloc(sizeof(char)*500);
char* title = (char*)malloc(sizeof(char)*100);
while(fgets(CSV, sizeof(CSV)*500,stdin))
{   
    fronttoken = strtok(CSV, "\"");     //store token until first quote, if no quote, store whole line
    title = strtok(NULL,"\"");          //store token after first quote until 2nd quote
    if(title != NULL)                   //if quotes in line, consume comma meant to delim title
    {
        token = strtok(NULL, ",");      //eat comma
    }
    backtoken = strtok(NULL,"\n");  //tokenize from second quote to \n character (remainder of line)

    printf("Front : %s\nTitle: %s\nBack: %s\n", fronttoken, title, backtoken);  //temp print statement to see front,back,title components

    token = strtok(fronttoken, ",");    //tokenizing front using comma delim
    while (token != NULL)
    {
        printf("%s\n", token);
        token = strtok(NULL, ",");
    }
    if (title != NULL)      //print if there is a title with comma
    {
        printf("%s\n",title);
    }   
    token = strtok(backtoken,",");  //tokenizing back using comma delim
    while (token != NULL)
    {
        printf("%s\n", token);
        token = strtok(NULL, ",");
    }
}

free(CSV);
free(token);    
free(fronttoken);
free(backtoken);
free(title);

return 0;

【问题讨论】:

  • while(fgets(CSV, sizeof(CSV)*500,stdin)) --> while(fgets(CSV, sizeof(*CSV)*500,stdin))
  • strtok 不分配内存,你不应该释放它返回的所有指针。
  • 除了@Jack 所说的之外,一旦您将strtok 的输出分配给指针,您使用malloc 创建的内存就会泄漏,因为您不再有指向它的指针来释放它。
  • malloc的返回不用强制转换,没必要。见:Do I cast the result of malloc?
  • 你脑子里有 sizeof...char *CSV = malloc(500); fgets(CSV, 500, stdin);

标签: c string memory-management malloc free


【解决方案1】:

关注这里:

char* title = (char*)malloc(sizeof(char)*100);
title = strtok(NULL,"\"");
  1. 您可以动态分配title 指向的内存。
  2. 您将strtok 的返回值分配给title,丢失任何 引用malloc()动态分配的内存!这 意味着您肯定会发生内存泄漏,因为您将 永远无法取消分配您动态分配的内存 之前。

strtok() 的 ref 示例有一个非常丰富的示例:

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

因此,无需为 strtok() 返回的内容分配内存 - 正如我之前解释的那样,这实际上很糟糕。

回到你的代码:

free(title);

什么都不做,因为此时titleNULL(因为strtok() 之后的while 循环。

token 相同。


此外,fronttokenbacktoken 也会导致内存泄漏,因为在调用malloc() 之后,它们被分配了strtok() 的返回值。但是它们的free() 也有问题(与titletoken 的其他取消分配相比),因为它们指向为CSV 分配的原始内存。

因此,当调用free(backtoken); 时,会发生双重释放或内存损坏。


此外,改变这个:

while(fgets(CSV, sizeof(CSV)*500,stdin))

到这里:

while(fgets(CSV, sizeof(*CSV)*500,stdin))

因为您想要CSV 指向的位置的大小(即您动态分配的内存大小)。

【讨论】:

  • free of fronttokenbacktoken 也存在问题,因为它们指向为 CSV 分配的原始内存中的某个位置,导致调用 free(backtoken) 时出现双重释放或损坏。
  • 非常感谢。我仍然是 C 的初学者,不知道何时在指针上使用 malloc。所以我应该只在制作数组时使用 malloc 吗?只是制作一个char*指针与在java中制作一个字符串相同并且可以更改吗?我仍然很困惑,但希望我最终能学会。
  • @codemonkey 欢迎您。您应该仅在必要时动态分配内存。查看strtok()的例子,学习指针。顺便说一句,如果答案对您有帮助,请点击我的答案左侧的勾号接受
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多