提问人:None 提问时间:10/24/2008 最后编辑:j0kNone 更新时间:9/18/2012 访问量:21460
Malloc 错误:释放对象的校验和不正确
Malloc Error: incorrect checksum for freed object
问:
我正在努力为一项任务实现尾巴。我让它正常工作,但是我似乎在随机时间从免费收到错误。
我看不出,要把它追溯到一个模式或除此之外的任何东西都是一致的。
例如,如果我将我的程序称为“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;
}
答:
我不确定它是否相关,但这两行对我来说似乎很可疑:
*(lines + slot) = (char *) malloc(len * sizeof(char));
if((lines + slot) == NULL) exit(EXIT_FAILURE);
您首先将 malloc 的返回值分配给,然后检查 ,如果后者为 NULL,则您取消了对 NULL 指针的引用!lines[slot]
(lines+slot)
此外,如果 lines[slot] (your *(lines+slot)) 不为 null,则在将 malloc() 的结果分配给它时,您将泄漏内存。
我假设是一个 *lines[]' 并且插槽在允许的边界内!lines
char
我同意 remo 对这两行的怀疑,但不同意 remo 偏离的切线。我们应该分享发现这个错误的功劳。
*(lines + slot) = some value
if((lines + slot) == NULL) then die
should be
if(*(lines + slot) == NULL) then die
评论
如果可以使用特定的输入参数一致地重现问题,则应按如下方式进行调试:
- 首先调试到导致问题的精确空闲。
- 然后弄清楚即将释放的内存何时被恶意释放。
- 接下来,调试到内存被恶意定位的位置。
- 在内存查看器中找到分配的内存块。记下块的开始和结束。在块之前和之后可能有一个称为保护块的特殊值。
- 现在单步执行代码,直到内存被释放。在某些时候,您的代码应该错误地覆盖保护块。这是令人反感的说法。
请注意,问题很可能出在程序的完全不同的部分。即使报告错误的是这个自由的,覆盖保护块的代码也可以在任何地方。
评论
我的第一个问题是你如何计算len?它只是 strlen 还是包括 \0 终结器的空间?我认为你可能在你的 strcpy 中超出了你的分配。不良行为往往会发生在单词边界上,并且看起来是随机的。此外,请检查以确保源字符串以 null 结尾。如果您在读取端犯了错误并且没有终止它们。然后 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;
您可以在其中引入调试非常糟糕的范围问题。
例程的写入超出了分配的行缓冲区。
作为参数传递的行的大小(即“len”)可能不包括 NUL 终止符。当你调用 malloc 复制行(即“s”)时,你需要为字符串终止符分配一个额外的字节:
*(lines + slot) = (char *) malloc((len + 1) * sizeof(char));
评论