2013-02-15 25 views
27

मैं हाल ही में मेरे PHP से निम्न त्रुटि मिल गया है:क्या भ्रष्ट डबल-लिंक्ड सूची 'का क्या मतलब है

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

मैं बहुत इस समस्या से परेशान नहीं कर रहा हूँ, और बहुत उसे ठीक करने में कोई दिलचस्पी नहीं। लेकिन मुझे यह समझने में बहुत दिलचस्पी है कि यह त्रुटि 'दूषित डबल-लिंक्ड सूची' वास्तव में क्या है, क्योंकि मैंने इसे पहले नहीं देखा है। मुझे विश्वास है कि एक डबल-लिंक्ड सूची क्या है, लेकिन मैं इस त्रुटि को ट्रिगर करने वाला प्रोग्राम तैयार करने में विफल रहा।

क्या कोई मुझे कोड का एक छोटा सा स्निपेट प्रदान कर सकता है जो ग्लिबल को दूषित और निष्पादित करते समय 'दूषित डबल-लिंक्ड सूची' कहने का कारण बनता है?

उत्तर

43

मैं अपने सवाल का जवाब अपने आप मिल गया है :)

तो मैं क्या समझ में नहीं आया था कि कैसे glibc एक segfault और एक दूषित डबल-लिंक्ड सूची के बीच अंतर कर सकता है, क्योंकि मेरी समझ के अनुसार, से 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;              \ 

तो अब यह अचानक समझ में आता है। ग्लिबैक यह जान सकता है कि यह एक डबल-लिंक्ड सूची है क्योंकि सूची ग्लिबैक का हिस्सा है। मैं उलझन में हूं क्योंकि मैंने सोचा था कि ग्लिबैक किसी भी तरह से पता लगा सकता है कि कुछ प्रोग्रामिंग एक डबल-लिंक्ड सूची बना रही है, जिसे मैं समझ नहीं पा रहा हूं कि यह कैसे काम करता है। लेकिन अगर यह डबल-लिंक्ड सूची जो इसके बारे में बात कर रही है, तो ग्लिबैक का हिस्सा है, बेशक यह जान सकता है कि यह एक डबल-लिंक्ड सूची है।

मुझे अभी भी पता नहीं है कि इस त्रुटि को किस प्रकार ट्रिगर किया गया है। लेकिन कम से कम मैं दूषित डबल-लिंक्ड सूची और सेगफॉल्ट के बीच का अंतर समझता हूं, और ग्लिबैक कैसे जान सकता है कि इस स्ट्रक्चर को डबल-लिंक्ड सूची माना जाता है :)

+21

हास्यास्पद होगा;) "बैड प्रोग्राम डिजाइन" -> * दुर्घटना * – mlvljr

1

यहां कोई भी समाधान ढूंढने वाले व्यक्ति के लिए, मैं सी ++: malloc() के साथ एक समान समस्या थी: छोटे से डबल डबल लिंक्ड सूची दूषित:

यह एक फ़ंक्शन के कारण था जो उस मान को वापस नहीं कर रहा था।

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

पता नहीं क्यों यह सब के बाद संकलित करने में सक्षम था। शायद इसके बारे में एक चेतावनी थी।

0

मैं इस त्रुटि में कुछ कोड में भाग गया जहां कोई एक थ्रेड में बाहर निकलने के लिए main() लौटा था, इसलिए सभी वैश्विक/स्थैतिक रचनाकारों को एक साथ दो अलग-अलग धागे में लात मार दिया गया था।

यह त्रुटि double free or corruption, या exit() के अंदर या malloc_consolidate के अंदर या शायद अन्य के रूप में एक segfault/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 list, malloc(): memory corruption, double free or corruption (!prev) तरह glibc चेतावनी के लिए दोष (लेकिन हमेशा नहीं) होना चाहिए।

यह निम्न कोड से reproduced किया जाना चाहिए:

#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) 

बग 12,693 == पर == में स्थित है 0x400A25: मुख्य (foo.cpp: 11)

0

यह विभिन्न कारणों से हो सकता है, कुछ अन्य उम्मीदवारों ने कहा और मैं परिचय दूंगा मेरे मामले को दोहराएं:

मुझे बहु-थ्रेडिंग (std::pthread और std::thread दोनों) का उपयोग करते समय यह त्रुटि मिली है और त्रुटि आई है क्योंकि मैं एक चर को लॉक करना भूल गया था जो एक ही समय में बहु थ्रेड बदल सकता है। यह त्रुटि कुछ रनों में यादृच्छिक रूप से आती है लेकिन सभी नहीं ... क्योंकि आप जानते हैं कि धागे के बीच दुर्घटना यादृच्छिक है।

मेरे मामले में चर एक वैश्विक std::vector जो मैं एक समारोह के धागे से बुलाया में उस में push_back() कुछ .. करने की कोशिश की और फिर मैं एक std::mutex का इस्तेमाल किया और फिर इस त्रुटि नहीं मिला था।

मदद मिल सकती है अगर glibs कि होशियार था कुछ