valgrind - Address ----在大小为8的块之后为0字节

时间:2014-12-24 11:36:44

标签: c linux valgrind

首先,我知道类似的问题。但是,我希望有一个更普遍的简单问题,真正原始的C数据类型。所以就是这样。

main.c中,我调用一个函数来填充这些字符串:

int
main (int argc, char *argv[]){

    char *host = NULL ;
    char *database ;
    char *collection_name;
    char *filename = ""; 
    char *fields = NULL;
    char *query = NULL;
    ...

    get_options(argc, argv, &host, &database, &collection_name, &filename, 
                &fields, &query, &aggregation);

内部get_options

if (*filename == NULL ) {
   *filename = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+4);
    strcpy(*filename, *collection_name);
    strcat(*filename, ".tde");  # line 69 
}

我的程序工作正常,但随后Valgrind告诉我,我做错了:

==8608== Memcheck, a memory error detector
==8608== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==8608== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==8608== Command: ./coll2tde -h localhost -d test -c test
==8608== 
==8608== Invalid write of size 1
==8608==    at 0x403BE2: get_options (coll2tde.c:69)
==8608==    by 0x402213: main (coll2tde.c:92)
==8608==  Address 0xa2edd18 is 0 bytes after a block of size 8 alloc'd
==8608==    at 0x4C28BED: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8608==    by 0x4C28D6F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8608==    by 0x403BBC: get_options (coll2tde.c:67)
==8608==    by 0x402213: main (coll2tde.c:92)

你能解释错误Address 0xa2edd18 is 0 bytes after a block of size 8 alloc'd吗? 我该如何解决这个问题?

2 个答案:

答案 0 :(得分:35)

strcpy添加空终止符'\0'。你忘了为它分配空间:

*filename = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+5);

您需要为5个字符添加空格:".tde"后缀为4,'\0'终结符为1。您当前的代码仅分配4,因此最后一次写入是在您为新文件名分配的块之后立即完成的(即,在它之后的0个字节)。

注意:您的代码有一个常见问题 - 它会将realloc的结果直接分配给重新分配的指针。 realloc成功时这很好,但在失败时会产生内存泄漏。修复此错误需要将realloc的结果存储在单独的变量中,并在将值重新分配回NULL之前检查*filename

char *tmp = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+5);
if (tmp != NULL) {
    *filename = tmp;
} else {
    // Do something about the failed allocation
}

直接分配给*filename会造成内存泄漏,因为*filename指向下方的指针会在失败时被覆盖,变为不可恢复。

答案 1 :(得分:0)

我刚收到此消息是因为我已经更改了一个类(添加了一个字段,因此更改了它的大小),并且没有重建所有包含标头的源。因此,某些模块仍尝试使用旧大小。