2008-10-24 98 views
9

我正在执行一个任务的尾部。我有它正常工作,但我似乎从随机时间免费获得一个错误。Malloc错误:释放对象的校验和不正确

我看不到,要追踪到一个模式或除了它是一致的任何东西。

例如,如果我将我的程序称为“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; 
} 
+0

是插槽0或1,根据? 插槽永远不会超过nlines-1,正确吗? – Dre 2008-10-24 07:10:09

+0

right模数自动回到0 – None 2008-10-24 07:15:13

+0

您使用哪个编译器和哪个调试器?根据这一点,他们可能会提供一些调试问题的帮助。 – 2008-10-24 08:03:43

回答

7

你的例程写入超出了分配的行缓冲区。

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

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

做nlines和numlines具有相同的价值?

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

+0

是的,nlines和numlines是相同的值。线的实际声明发生在别的地方。空值由调用函数进行计算。 – None 2008-10-24 07:16:27

0

我不知道它是相关的,但这两行看起来可疑对我说:

*(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))不为null,则会在将malloc()的结果赋给它时泄漏内存。

我假设lineschar * lines []`并且slot在允许的边界内!

0

我同意REM对这两条线的怀疑,但不同意REM给出的切线。我们应该分享功劳来找到这个错误。

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

如果可以一致地重现与特定输入参数的问题,您应该调试是这样的:

  • 首先调试的精确自由引起该问题。
  • 然后计算出将要被释放的内存何时被malloc化。
  • 接下来,调试到内存malloc'ed的地方。
  • 在内存查看器中找到已分配的内存块。注意块的开始和结束。在该块之前和之后可能有一个特殊值,称为保护块
  • 现在遍历代码,直到内存被释放。在某些时候,你的代码应该错误地覆盖了保护块。 这是违规的陈述。

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

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; 

在这里您可以引入范围的问题是只可怜的调试。

相关问题