问题 什么是glibc free / malloc / realloc无效的下一个大小/无效指针错误以及如何解决它?


您很可能会看到这个问题,因为您的问题已被关闭,因为它与此重复。有关相关问题的中等完整列表,请参阅 一长串可能的重复项 - C内存分配和超限界限 在Meta Stack溢出。


示例问题

免费char *:下一个大小无效(快) 问道 noobie 在2014-04-11。

我正在释放一个 char* 在连接过程之后,但是我收到此错误:

free(): invalid next size (fast): 0x0000000001b86170

这是我的代码:

void concat(stringList *list) {
    char *res = (char*)malloc(sizeof(char*));

    strcpy(res, list->head->string);

    list->tmp = list->head->next;
    while (list->tmp != NULL) {
        strcat(res, ",");
        strcat(res, list->tmp->string);
        list->tmp = list->tmp->next;
    }

    printf("%s\n", res);
    free(res);
}

通用问题

运行我的程序时,我看到如下错误消息:

*** glibc detected *** ./a.out: free(): corrupted unsorted chunks: 0x12345678 ***

详细信息可以包含以下任何内容 *** glibc detected *** 和程序名称,消息后跟一个十六进制地址(显示为0x12345678)和另一个 ***

  • free(): corrupted unsorted chunks: 0x12345678
  • free(): invalid next size (fast): 0x12345678
  • free(): invalid next size (normal): 0x12345678
  • free(): invalid pointer: 0x12345678
  • free(): invalid size: 0x12345678
  • malloc(): corrupted unsorted chunks: 0x12345678
  • malloc(): corrupted unsorted chunks 2: 0x12345678
  • malloc(): memory corruption: 0x12345678
  • malloc(): memory corruption (fast): 0x12345678
  • malloc(): smallbin double linked list corrupted: 0x12345678
  • munmap_chunk(): invalid pointer: 0x12345678
  • realloc(): invalid next size (fast): 0x12345678
  • realloc(): invalid old size (fast): 0x12345678
  • realloc(): invalid pointer: 0x12345678
  • corrupted double-linked list: 0x12345678

调用时会发生这种情况 frobnicate() 功能;这个功能出了什么问题?


5475
2018-05-15 13:53


起源

我得到了意图,但目标用户不会发现这个。 - this
@self。:请看 meta.stackoverflow.com/questions/254782 - PlasmaHH


答案:


回答示例问题

放松 接受了 回答 示例问题:

你的代码错了。

您正在为单个指针分配空间(malloc(sizeof(char*))),但没有人物。您将使用所有字符串覆盖已分配的空间,从而导致未定义的行为(在此特定情况下,会损坏 malloc()的簿记数据)。

您不需要为指针分配空间(res);这是一个局部变量。您 必须 为您希望存储在指针所占地址的所有字符分配空间。

由于您将遍历列表以查找要连接的字符串,因此您无法预先知道总大小。你将不得不在列表上进行两次传递:一次总结 strlen() 每个字符串,然后为分隔符和终止符分配该空间,然后在实际进行连接时再分配另一个字符串。

通用答案

你所看到的是glibc分配器内部结构损坏的结果。在分配或释放动态内存时,分配器必须管理它从操作系统保留的内存,并根据您请求的操作找到要分发的新块,将释放的块排序到它的列表中可以再次发出,或者将内存返回给操作系统。这些错误消息表明它用于管理此功能的数据结构已损坏。

这些错误都意味着你的一些代码修改了它没有被使用的内存,调用 未定义的行为。这很可能是在你的程序中更早地覆盖一些内存的结果,并且完全有可能错误不在于 frobnicate() 功能。

是的,这意味着错误可以 程序中的任何位置或您使用的第三方库

这可能不是Stack Overflow的好问题。除非您对问题进行简单的简单复制,否则此社区可能无法为您提供帮助。错误的原因可能在您的代码中的任何位置(并且通常不在发现错误的函数中),并且它可能在我们看不到的代码中。 Stack Overflow是  协作调试站点。即使有人能够在您的代码中找到缺陷,您的具体问题也不太可能对未来的访问者有所帮助。

常见原因

  • 免费使用。 你已经释放/删除了一些内存,然后写入了它,覆盖了glibc记账所需的结构。
  • N次错误。 您正在将已分配的块之后的N个字节写入glibc内部用于其簿记的未分配内存中。
  • 未初始化的指针。 您没有初始化指针。巧合的是,它指向glibc保留的一些内存,但是没有由你的程序分配并且你写入它。
  • 分配错误的空间量。  这可能是因为你写的 long *data = malloc(number * 4) 代替 long *data = malloc(number * sizeof(long)); 或更好) long *data = malloc(number * sizeof(*data));。还有许多其他方法可以使尺寸计算错误。另一个常见的问题是忘记在字符串末尾考虑空终止符: char *copy = malloc(strlen(str)); 代替 char *copy = malloc(strlen(str)+1);

你现在需要做的就是卷起袖子并调试这个问题

没有简单的答案可以找到什么,或者要修复什么。没有一个你使用错误的单一语法结构。这个bug的原因可能有几千种。

工具

  • 的valgrind 创建的工具主要是为了找到这种错误。如果找不到任何东西,请确保您使用的是最新版本,并且您也在尝试使用最新版本 exp-sgcheck 工具。如果您正在运行多线程代码,原因可能也与竞争条件有关,因此您可能希望尝试包含的竞争条件检查器 drd 和 helgrind 了解更多信息。在撰写本文时,valgrind支持以下平台:
    • X86 / Linux的,
    • AMD64 / Linux的,
    • ARM / Linux的,
    • PPC32 / Linux的,
    • PPC64 / Linux的,
    • S390X / Linux的,
    • MIPS32 / Linux的,
    • MIPS64 / Linux的,
    • ARM / Android(2.3.x及更高版本),
    • X86 / Android(4.0及更高版本),
    • X86 /达尔文和
    • AMD64 / Darwin(Mac OS X 10.7,支持10.8)。
  • 净化 与valgrind类似的工具,但是商业化并针对不同的平台集。
  • AddressSanitizer 一个类似的工具,但集成到编译器工具链(gcc和clang)中。
  • 用efence 分配器替换的下降将尝试使程序先前崩溃,以便您可以找到正常的调试器,其中发生了对无效内存的写入。
  • dmalloc 一个与efence目的相似的图书馆。

需要更多的帮助

如果使用这些工具无法解决问题,则应尝试创建MCVE(如何创建一个最小,完整和可验证的示例?)或者,相当于一个SSCCE(短,自包含,正确(可编译),示例)。

请记住处理代码的副本,因为创建MCVE需要您无情地删除无助于重现问题的代码。使用VCS(版本控制系统)来提供帮助是一个好主意;您可以记录将问题降至最低的中间阶段。它可能是一个新的丢弃存储库,只是为了将您的问题减少到可管理的大小。

通过良好的模块化设计,您可以相对轻松地创建MCVE。也许你已经有一个单元测试,更适合用于上述工具之一。您也可能只想创建一个以后可以作为此错误的回归测试。


12
2018-05-15 13:53