【问题标题】:Malloc Error: incorrect checksum for freed objectMalloc 错误:释放对象的校验和不正确
【发布时间】:2010-09-18 23:04:26
【问题描述】:

我正在为一项任务实现tail。我让它正常工作,但我似乎在随机时间免费收到错误。

我看不到,要追查到一个模式或除此之外的任何东西是一致的。

例如,如果我将我的程序称为“tail -24 test.in”,我会在多次运行的同一行中得到不正确的校验和错误。但是,如果要打印不同的文件甚至不同的行数,我会毫无错误地返回。

关于如何追踪问题的任何想法,我一直在尝试调试它几个小时无济于事。

这是有问题的代码:

lines 被定义为一个 char** 并且被 malloc 为:

lines = (char**) malloc(nlines * sizeof(char *));

void insert_line(char *s, int len){

  printf("\t\tLine Number: %d Putting a %d line into slot: %d\n",processed,len,slot);
  if(processed > numlines -1){//clean up
    free(*(lines+slot));
    *(lines + slot) = NULL;
  }
  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
  strcpy(*(lines+slot),s);
  slot = ++processed % numlines;
}

【问题讨论】:

  • 是基于插槽 0 还是插槽 1?插槽永远不会超过 nlines-1,对吗?
  • 正确的模数自动回到0左右
  • 您使用的是哪个编译器和调试器?根据这一点,他们可能能够为调试您的问题提供一些帮助。
  • 我建议用 lines = (char **) calloc(nlines, sizeof(char *)); 替换原来的 malloc 行calloc 的优点是内存为您清零,因此您将从所有 NULL 指针开始。

标签: c debugging pointers malloc


【解决方案1】:

您的例程正在写入超出分配的行缓冲区。

作为参数传递的行的大小(即“len”)可能不包括 NUL 终止符。当您调用 malloc 复制行(即“s”)时,您需要为字符串终止符分配一个额外的字节:

 *(lines + slot) = (char *) malloc((len + 1) * sizeof(char));

【讨论】:

  • 这个答案是如何被接受的?在发布此答案的前一天,原发帖者对我的答案发表了评论,称“null 由调用函数负责。”
【解决方案2】:

如果你可以用特定的输入参数持续重现问题,你应该像这样调试:

  • 首先调试到导致问题的确切免费。
  • 然后找出即将被释放的内存何时被分配。
  • 接下来,调试到内存 malloc 的地方。
  • 在内存查看器中找到分配的内存块。注意块的开始和结束。可能有一个特殊的值,称为 保护块,就在块之前和之后。
  • 现在单步执行代码,直到内存被释放。在某些时候,您的代码应该错误地覆盖保护块。 这是有问题的陈述。

请注意,问题很可能出在程序的完全不同的部分。即使是这个免费报告错误,覆盖保护块的代码也可以在任何地方。

【讨论】:

  • 包含了null,你看到的代码是我对指针进行操作的唯一地方。很奇怪。
  • 其他一些代码可能正在其分配的内存之外写入并写入块周围的保护值。这就是为什么您需要单步执行 malloc 和 free 之间的所有代码。在某些时候,某些代码会覆盖其中一个保护值。
【解决方案3】:

我的第一个问题是如何计算 len?它只是 strlen 还是包含 \0 终止符的空间?我认为您可能超出了您在 strcpy 中的分配。不良行为往往会发生在单词边界上并且显得随机。此外,请检查以确保您的源字符串以空值结尾。如果您在读取端犯了错误并且没有终止它们。那么 strcpy 可能会随机覆盖事物。

  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
  strcpy(*(lines+slot),s);

或许可以试试:

  lines[slot] = (char *) malloc((len + 1) * sizeof(char));
  if(lines[slot] == NULL) exit(EXIT_FAILURE);
  if(strlen(s) <= len){
    strcpy(lines[slot],s);
  }
  else{
    /* do something else... */
  }

就一般形式而言,我还鼓励您进行一些风格上的更改,以使整个内容更具可读性、更易于理解和抗错。

指针算法是有效且有趣的,但我认为如果你使用数组形式,你的意图会更清楚一点:

free(lines[slot]);
lines[slot] = NULL;

而不是

free(*(lines+slot));
*(lines + slot) = NULL;

我还鼓励您使用更少的静态参数。在数据结构中通过它们并将它们传递给您的访问器和修改器很容易。动作发生的位置会变得更加清晰,从而阻止您执行以下操作:

static int numlines = 0;
void insert_line(char *s, int len){
    int numlines = 5;

您可以在其中引入难以调试的范围问题。

【讨论】:

    【解决方案4】:

    nlines 和 numlines 是否具有相同的值?

    insert_line 的调用者在传递第二个参数中的长度时是否为尾随的 NUL 留出空间?

    【讨论】:

    • 是的,nlines 和 numlines 是相同的值。行的实际声明发生在其他地方。 null 由调用函数计算。
    【解决方案5】:

    我不确定它是否相关,但这两行对我来说似乎很可疑:

      *(lines + slot) = (char *) malloc(len * sizeof(char));
      if((lines + slot) == NULL) exit(EXIT_FAILURE);
    

    您首先将 malloc 的返回值分配给 lines[slot],然后检查 (lines+slot),如果后者为 NULL,则您已取消引用 NULL 指针!

    此外,如果 lines[slot] (你的 *(lines+slot)) 不为空,当你将 malloc() 的结果分配给它时,你会泄漏内存。

    我假设 lineschar*lines[]` 并且插槽在允许的范围内!

    【讨论】:

      【解决方案6】:

      我同意 remo 对这两行的怀疑,但不同意 remo 的切线。我们应该分享发现这个错误的功劳。

      *(lines + slot) = some value
      if((lines + slot) == NULL) then die
      should be
      if(*(lines + slot) == NULL) then die
      

      【讨论】:

      • 嘿,您在我编辑此答案时编辑了您的源代码。在这种情况下,您的错误可能在您尚未编辑的程序的其他部分......
      • 我实际上已经修复了它......这不是导致我的 malloc 错误的原因
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2011-08-04
      • 2013-11-19
      • 1970-01-01
      相关资源
      最近更新 更多