Malloc错误:释放对象的校验和不正确

时间:2008-10-24 06:53:08

标签: c debugging pointers malloc

我正在为作业实施tail。我让它正常工作但是我似乎在随机时间免费获得错误。

我无法看到,将其追踪到一个模式或除此之外的任何事情都是一致的。

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

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

以下是有问题的代码:

行被定义为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;
}

6 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分:3)

如果您可以使用特定输入参数一致地重现问题,则应按以下方式进行调试:

  • 首先调试导致问题的精确自由。
  • 然后弄明白即将被释放的内存是malloc'ed。
  • 接下来,调试内存为malloc的地方。
  • 在内存查看器中找到已分配的内存块。注意块的开始和结束。在块之前和之后可能存在称为保护块的特殊值。
  • 现在逐步执行代码,直到内存空闲为止。在某些时候,您的代码应该错误地覆盖保护块。 这是令人不快的陈述。

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

答案 2 :(得分:1)

我的第一个问题是你如何计算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;

您可以在其中介绍仅对调试感到悲惨的范围问题。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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

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

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

如果行[slot](你的*(行+插槽))不为null,当你将malloc()的结果赋给它时,你将泄漏内存。

我认为lineschar *行[]`并且插槽位于允许的边界内!

答案 5 :(得分:0)

我同意雷莫对这两条线的怀疑,但不同意雷莫的切线。我们应该分享信用来发现这个错误。

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