2013-02-15 38 views
27

我最近得到了從我的PHP以下錯誤:什麼是「破壞雙鏈表」的意思

WARNING: [pool www] child 42475 said into stderr: "*** glibc detected *** php-fpm: pool www: corrupted double-linked list: 0x00000000013fe680 ***" 

我不會受到此問題困擾極,並在修復它不是很感興趣。 但我對於理解這個錯誤「損壞的雙向鏈表」的含義非常感興趣,因爲我之前沒有看到它。我相信要知道雙鏈表是什麼,但是我沒有產生觸發這個錯誤的程序。

有人能給我提供一小段代碼,當我編譯並執行它時,會導致glibc說'已損壞的雙鏈表'。

回答

43

我已經找到了答案,我的問題我自己:)

所以我不明白的是glibc的如何能段錯誤和損壞的雙鏈表區分,因爲根據我的理解,從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如何知道這個結構應該是一個雙向鏈表:)

+21

將是有趣的,如果glibs是聰明;) 「壞程序設計」 - > *崩潰* – mlvljr 2013-05-31 23:31:36

1

對於任何正在尋找解決方案的人,有與C++類似的問題: malloc():smallbin雙鏈表損壞:

這是由於函數沒有返回它應該的值。

std::vector<Object> generateStuff(std::vector<Object>& target> { 
    std::vector<Object> returnValue; 
    editStuff(target); 
    // RETURN MISSING 
} 

不知道爲什麼這是能夠編譯畢竟。可能有關於它的警告。

0

我在某些代碼中遇到了這個錯誤,因爲有人在一個線程中調用exit()的時間與返回的main()相同,因此所有全局/靜態構造函數都在兩個獨立線程中同時啓動。

該錯誤還表現爲double free or corruptionexit()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下運行時出現此問題。

13

堆溢出應該是corrupted double-linked listmalloc(): memory corruptiondouble 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; 
} 

如果使用克++(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-7f00 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 

,如果編譯使用鐺++(6.0(鐺-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) 

這個bug位於== 12693 ==在0x400A25:main(foo.cpp:11)

0

這可能是由於不同的原因造成的,有的說其他的候選人我會介紹導致我的情況:

當使用多線程時(std::pthreadstd::thread)出現此錯誤,並且發生錯誤是因爲我忘記鎖定多線程可能同時更改的變量。 這個錯誤在一些運行中隨機出現,但不是全部,因爲......你知道線程之間的意外是隨機的。

,在我的情況下,變量是一個全球性的std::vector我試圖push_back()東西在它在一個由線程調用的函數..然後我用一個std::mutex也再沒有得到這個錯誤。

可以幫助一些