什么是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代码,则原因可能也与竞争条件有关,因此您可能需要尝试使用包含竞争条件检查程序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 /达尔文(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。