【问题标题】:What is a glibc free/malloc/realloc invalid next size/invalid pointer error and how to fix it?什么是 glibc free/malloc/realloc invalid next size/invalid pointer 错误以及如何解决?
【发布时间】:2014-07-04 00:35:11
【问题描述】:

您很可能会看到此问题,因为您的问题已作为此问题的副本关闭。有关相关问题的完整列表,请参阅 Meta Stack Overflow 上的A long list of possible duplicates — C memory allocation and overrunning bounds


示例问题

来自free char*: invalid next size (fast)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() 函数时;那个函数有什么问题?

【问题讨论】:

标签: c++ c memory glibc


【解决方案1】:

示例问题的答案

unwind 将接受的answer 提供给示例问题:

你的代码错了。

您正在为单个指针 (malloc(sizeof(char*))) 分配空间,但没有字符。您正在用所有字符串覆盖分配的空间,导致未定义的行为(在这种特殊情况下,破坏了malloc() 的簿记数据)。

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

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

通用答案

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

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

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

这对于 Stack Overflow 来说可能不是一个好问题。除非您能很好地简单地重现您的问题,否则这个社区可能无法为您提供太多帮助。错误的原因可能在您的代码中的任何地方(并且通常不在发现错误的函数中),并且可能在我们看不到的代码中。 Stack Overflow 不是一个协作调试站点。即使有人可以发现您的代码中的缺陷,您的具体问题也不可能对任何未来的访问者有所帮助。

常见原因

  • 释放后使用。您已经释放/删除了一些内存,然后写入其中,覆盖了 glibc 记账所需的结构。
  • Off-by-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);

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

没有简单的答案要寻找什么,或者要修复什么。您没有使用错误的单个语法结构。这个错误的原因可能有成千上万种。

工具

  • valgrind 主要用于准确查找此类错误的工具。如果它找不到任何东西,请确保您使用的是最新版本,并且您也在尝试包含的 exp-sgcheck 工具。如果您正在运行多线程代码,则原因也可能与竞争条件有关,因此您可能想尝试包含的竞争条件检查器drdhelgrind 以获得更多信息。在撰写本文时,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 的支持有限)。
  • purify 与 valgrind 类似的工具,但商业化并针对不同的平台集。
  • AddressSanitizer 类似的工具,但集成到编译器工具链(gcc 和 clang)中。
  • efence 替换分配器会尝试更早地使您的程序崩溃,这样您就可以使用正常的调试器找出写入无效内存的位置。
  • dmalloc 一个与 efence 用途相似的库。

需要更多帮助

如果您无法使用这些工具解决问题,则应尝试创建 MCVE (How to create a Minimal, Complete, and Verifiable Example?) 或等效的 SSCCE (Short, Self Contained, Correct (Compilable), Example)。

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

通过对代码进行良好的模块化设计,创建 MCVE 应该相对容易。也许您也已经有了一个更适合输入上述工具之一的单元测试。您也可能只想创建一个以后可以用作此错误的回归测试。

【讨论】:

    猜你喜欢
    • 2013-04-20
    • 2011-01-19
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    • 2017-07-16
    相关资源
    最近更新 更多