我最近从我的PHP中收到了以下错误:
WARNING: [pool www] child 42475 said into stderr: "*** glibc detected *** php-fpm: pool www: corrupted double-linked list: 0x00000000013fe680 ***"
我对这个问题并不感到困扰,对修复它并不是很感兴趣。 但是我非常有兴趣了解这个错误'损坏的双链表'究竟意味着什么,因为我以前没见过它。我相信知道双链表是什么,但是我没能产生一个触发这个错误的程序。
当我编译并执行它时,有人能为我提供一小段代码,导致glibc说“损坏的双链表”吗?
答案 0 :(得分:52)
我自己找到了问题的答案:)
所以我不明白的是glibc如何区分Segfault和损坏的双链表,因为根据我的理解,从glibc的角度看它们看起来应该是一样的。 因为如果我在程序中实现双链表,glibc怎么可能知道这是一个双链表,而不是任何其他结构?它可能不会,所以这就是为什么我感到困惑。
现在我在glibc的代码中查看了malloc / malloc.c,我看到了以下内容:
1543 /* Take a chunk off a bin list */
1544 #define unlink(P, BK, FD) { \
1545 FD = P->fd; \
1546 BK = P->bk; \
1547 if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
1548 malloc_printerr (check_action, "corrupted double-linked list", P); \
1549 else { \
1550 FD->bk = BK; \
1551 BK->fd = FD; \
所以现在这突然变得有意义了。 glibc之所以知道这是一个双链表是因为列表是glibc本身的一部分。我一直很困惑,因为我认为glibc可以以某种方式检测到某些编程正在构建一个双链表,我不明白它是如何工作的。但如果它所讨论的这个双链表是glibc本身的一部分,当然它可以知道它是一个双链表。
我仍然不知道触发此错误的原因。但至少我理解损坏的双链表和Segfault之间的区别,以及glibc如何知道这个结构应该是一个双链表:)
答案 1 :(得分:19)
corrupted double-linked list
,malloc(): memory corruption
,double free or corruption (!prev)
来说,堆溢出应该是责备(但并非总是如此) - 就像glibc警告一样。
应该通过以下代码复制:
#include <vector>
using std::vector;
int main(int argc, const char *argv[])
{
int *p = new int[3];
vector<int> vec;
vec.resize(100);
p[6] = 1024;
delete[] p;
return 0;
}
如果使用g ++(4.5.4)编译:
$ ./heapoverflow
*** glibc detected *** ./heapoverflow: double free or corruption (!prev): 0x0000000001263030 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7af26)[0x7f853f5d3f26]
./heapoverflow[0x40138e]
./heapoverflow[0x400d9c]
./heapoverflow[0x400bd9]
./heapoverflow[0x400aa6]
./heapoverflow[0x400a26]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x7f853f57b4bd]
./heapoverflow[0x4008f9]
======= Memory map: ========
00400000-00403000 r-xp 00000000 08:02 2150398851 /data1/home/mckelvin/heapoverflow
00602000-00603000 r--p 00002000 08:02 2150398851 /data1/home/mckelvin/heapoverflow
00603000-00604000 rw-p 00003000 08:02 2150398851 /data1/home/mckelvin/heapoverflow
01263000-01284000 rw-p 00000000 00:00 0 [heap]
7f853f559000-7f853f6fa000 r-xp 00000000 09:01 201329536 /lib64/libc-2.15.so
7f853f6fa000-7f853f8fa000 ---p 001a1000 09:01 201329536 /lib64/libc-2.15.so
7f853f8fa000-7f853f8fe000 r--p 001a1000 09:01 201329536 /lib64/libc-2.15.so
7f853f8fe000-7f853f900000 rw-p 001a5000 09:01 201329536 /lib64/libc-2.15.so
7f853f900000-7f853f904000 rw-p 00000000 00:00 0
7f853f904000-7f853f919000 r-xp 00000000 09:01 74726670 /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.1/libgcc_s.so.1
7f853f919000-7f853fb19000 ---p 00015000 09:01 74726670 /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.1/libgcc_s.so.1
7f853fb19000-7f853fb1a000 r--p 00015000 09:01 74726670 /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.1/libgcc_s.so.1
7f853fb1a000-7f853fb1b000 rw-p 00016000 09:01 74726670 /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.1/libgcc_s.so.1
7f853fb1b000-7f853fc11000 r-xp 00000000 09:01 201329538 /lib64/libm-2.15.so
7f853fc11000-7f853fe10000 ---p 000f6000 09:01 201329538 /lib64/libm-2.15.so
7f853fe10000-7f853fe11000 r--p 000f5000 09:01 201329538 /lib64/libm-2.15.so
7f853fe11000-7f853fe12000 rw-p 000f6000 09:01 201329538 /lib64/libm-2.15.so
7f853fe12000-7f853fefc000 r-xp 00000000 09:01 74726678 /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.1/libstdc++.so.6.0.18
7f853fefc000-7f85400fb000 ---p 000ea000 09:01 74726678 /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.1/libstdc++.so.6.0.18
7f85400fb000-7f8540103000 r--p 000e9000 09:01 74726678 /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.1/libstdc++.so.6.0.18
7f8540103000-7f8540105000 rw-p 000f1000 09:01 74726678 /usr/lib64/gcc/x86_64-pc-linux-gnu/4.8.1/libstdc++.so.6.0.18
7f8540105000-7f854011a000 rw-p 00000000 00:00 0
7f854011a000-7f854013c000 r-xp 00000000 09:01 201328977 /lib64/ld-2.15.so
7f854031c000-7f8540321000 rw-p 00000000 00:00 0
7f8540339000-7f854033b000 rw-p 00000000 00:00 0
7f854033b000-7f854033c000 r--p 00021000 09:01 201328977 /lib64/ld-2.15.so
7f854033c000-7f854033d000 rw-p 00022000 09:01 201328977 /lib64/ld-2.15.so
7f854033d000-7f854033e000 rw-p 00000000 00:00 0
7fff92922000-7fff92943000 rw-p 00000000 00:00 0 [stack]
7fff929ff000-7fff92a00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
[1] 18379 abort ./heapoverflow
如果使用clang ++(6.0(clang-600.0.56)编译):
$ ./heapoverflow
[1] 96277 segmentation fault ./heapoverflow
如果您认为自己可能编写了类似的错误,可以在此处找到一些提示。
首先,使用调试标志(-g
)编译代码:
g++ -g foo.cpp
然后,使用valgrind:
运行它$ valgrind ./a.out
==12693== Memcheck, a memory error detector
==12693== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==12693== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==12693== Command: ./a.out
==12693==
==12693== Invalid write of size 4
==12693== at 0x400A25: main (foo.cpp:11)
==12693== Address 0x5a1c058 is 12 bytes after a block of size 12 alloc'd
==12693== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12693== by 0x4009F6: main (foo.cpp:8)
==12693==
==12693==
==12693== HEAP SUMMARY:
==12693== in use at exit: 0 bytes in 0 blocks
==12693== total heap usage: 2 allocs, 2 frees, 412 bytes allocated
==12693==
==12693== All heap blocks were freed -- no leaks are possible
==12693==
==12693== For counts of detected and suppressed errors, rerun with: -v
==12693== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
该错误位于 == 12693 == 0x400A25:main(foo.cpp:11)
答案 2 :(得分:2)
一个同事遇到此错误,发现在代码的某个地方他在列表的某个元素上犯了此错误:
std::string listElement = listElement = someObject.getName();
显然不是:
std::string listElement = someObject.getName();
这似乎无关紧要,但是每次运行都会出现错误,我们可以在清理所有内容后重现它,而仅更改此行即可解决问题。
希望有一天有帮助。...
答案 3 :(得分:1)
对于那些在这里寻找解决方案的人来说,我遇到了与C ++类似的问题: malloc():smallbin双链表损坏:
这是因为函数没有返回它应该的值。
std::vector<Object> generateStuff(std::vector<Object>& target> {
std::vector<Object> returnValue;
editStuff(target);
// RETURN MISSING
}
毕竟不知道为什么能够编译。可能会有一个警告。
答案 4 :(得分:1)
这可能由于不同的原因,一些人说其他候选人,我将介绍我的案例:
使用多线程(std::pthread
和std::thread
时)出现此错误,并且发生错误,因为我忘记锁定多线程可能同时更改的变量。
这个错误在一些运行中随机出现,但并非全部,因为......你知道线程之间的意外是随机的。
在我的情况下,该变量是一个全局std::vector
,我试图在一个由线程调用的函数中push_back()
中的某些内容...然后我使用std::mutex
并且从未得到过这个再次出错。
可能有所帮助
答案 5 :(得分:0)
我在某些代码中遇到了这个错误,其中有人在返回main()
的同时在一个线程中调用exit(),因此所有全局/静态构造函数都在两个单独的线程中同时启动。
此错误也会显示为double free or corruption
,或exit()
内或malloc_consolidate
内的段错误/ sig11,以及其他可能的错误。 malloc_consolidate崩溃的调用堆栈可能类似于:
#0 0xabcdabcd in malloc_consolidate () from /lib/libc.so.6
#1 0xabcdabcd in _int_free () from /lib/libc.so.6
#2 0xabcdabcd in operator delete (...)
#3 0xabcdabcd in operator delete[] (...)
(...)
在valgrind下运行时,我无法表现出这个问题。