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

你最有可能看到这个问题,因为你的问题已经被封闭,作为这个副本。 有关相关问题的中等完整列表,请参阅可能重复的长列表 – C堆内存分配和元堆栈溢出溢出边界 。


示例问题

从免费字符*:无效的下一个大小(快)在2014-04-11由noobie问。

我在一个串联进程后释放一个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 ***和程序名后,详细信息可以包含以下任何信息,消息后面跟着一个hex地址(显示为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()函数时发生这种情况; 这个function有什么问题?

回答示例问题

放松给了这个问题的答案 :

你的代码是错误的。

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

您不需要为指针( res )分配空间; 这是一个局部variables。 您必须为指针所保存的地址处的所有字符分配空间。

既然你要遍历一个列表来查找要连接的string,你不能预先知道总的大小。 你将不得不在列表上进行strlen() :一个是对每个string的strlen()进行求和,然后为分隔符和终止符分配加号空间,然后在实际进行并置时再进行一次。

通用答案

你所看到的是glibc分配器内部结构腐败的结果。 在分配或释放dynamic内存时,分配器必须pipe理它从操作系统保留的内存,并根据您所请求的操作,find一个新的分块,将释放的分块分类到其中的分块可以稍后再交出,或者把内存送回操作系统。 这些错误消息显示它用于pipe理此function的数据结构已损坏。

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

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

这可能不是一个好堆栈溢出的问题。 除非你有一个很好的简单再现你的问题,这个社区可能无法帮助你很多。 错误的原因可能在代码中的任何地方(并且通常不在错误被发现的函数中),并且可能在我们看不到的代码中。 堆栈溢出不是一个协作式的debugging网站。 即使有人可以在代码中发现缺陷,您的具体问题也不可能对未来的访问者有所帮助。

常见原因

  • 免费后使用。 你已经释放/删除了一些内存,然后写入内存,覆盖glibc需要记帐的结构。
  • closuresN错误。 您将在分配的块之后写入N个字节到glibc内部用于簿记的未分配内存中。
  • 未初始化的指针。 您没有初始化指针。 巧合的是它指向一些由glibc保留的内存,但不是由程序分配的,而是写入到内存中。
  • 分配错误的空间量。 这可能是因为你写了long *data = malloc(number * 4)而不是long *data = malloc(number * sizeof(long)); 或者(更好) long *data = malloc(number * sizeof(*data)); 。 还有很多其他的方法来计算错误的大小。 另一个常见的情况是忘记在string末尾加上空终止字符: char *copy = malloc(strlen(str)); 而不是char *copy = malloc(strlen(str)+1);

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

没有简单的答案要找什么,或者要解决什么问题。 没有单一的句法结构,你使用错了。 这个错误的原因可能来自数千个品种。

工具

  • valgrind主要是为了find这种错误而创build的工具。 如果找不到任何东西,请确保您使用的是最新版本,并且您也正在尝试使用包含的exp-sgcheck工具。 如果您正在运行multithreading代码,则原因可能也与竞争条件有关,因此您可能需要尝试使用包含竞争条件检查程序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 /达尔文(Mac OS X 10.7,有限的支持10.8)。
  • 净化类似的工具Valgrind,但商业和针对不同的平台。
  • AddressSanitizer一个类似的工具,但集成到编译器工具链(gcc和clang)中。
  • 防止分配器replace的一个下降,它将尝试更早地崩溃你的程序,这样你就可以find一个普通的debugging器,在那里写入无效的内存。
  • dmalloc一个类似于efence的库。

需要更多的帮助

如果你不能用这些工具解决你的问题,你应该尝试创build一个MCVE( 如何创build一个最小的,完整的和可validation的例子? ),或者相当于一个SSCCE( 短的,自包含的,正确的(可编译的) ,例子 )。

请记住在你的代码的副本上工作,因为创build一个MCVE需要你无情地删除代码,这不会帮助重现问题。 使用VCS(版本控制系统)来帮助是一个好主意; 您可以logging中间阶段,将问题降至最低。 它可能是一个新的丢弃存储库,只是为了减less你的问题到一个可pipe理的大小。

通过对代码进行良好的模块化devise,创buildMCVE应该相对容易。 也许你已经有一个unit testing,更适合上述的工具之一。 你也可能只是想创build一个可以稍后作为这个bug的回归testing。