valgrind - 地址 ---- 在大小为 8 的块分配后为 0 个字节

新手上路,请多包涵

首先,我知道有人问过 类似 的问题。但是,我想对真正原始的 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 吗?我该如何解决这个问题?

原文由 oz123 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 803
2 个回答

strcpy 添加空终止符 '\0' 。您忘记为其分配空间:

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

您需要为 5 个字符添加空格:4 个用于 ".tde" 后缀,另外一个用于 '\0' 终止符。您当前的代码仅分配 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 一直指向的指针在失败时会被覆盖,变得不可恢复。

原文由 Sergey Kalinichenko 发布,翻译遵循 CC BY-SA 3.0 许可协议

我刚刚收到此消息,因为我更改了一个类(添加了一个字段,所以我更改了它的大小)并且没有重建包含标题的所有源。所以一些模块仍然试图使用旧的尺寸。

原文由 Algoman 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题