Que signifie "liste double liée corrompue"
j'ai récemment reçu l'erreur suivante de mon PHP:
WARNING: [pool www] child 42475 said into stderr: "*** glibc detected *** php-fpm: pool www: corrupted double-linked list: 0x00000000013fe680 ***"
je ne suis pas très gêné par ce problème, et pas très intéressé à le résoudre. Mais je suis très intéressé de comprendre ce que cette erreur "Liste double-liée corrompue" signifie réellement, parce que je ne l'ai pas vu avant. Je crois savoir ce qu'est une liste double-liée, mais j'ai échoué à produire un programme qui déclenche cette erreur.
quelqu'un Pourrait me fournir un court extrait de code qui provoque l' glibc pour dire "liste double-liée corrompue" quand je le compilerai et l'exécuterai?
5 réponses
j'ai moi-même trouvé la réponse à ma question:)
alors ce que je n'ai pas compris, c'est comment la glibc pouvait faire la différence entre un Segfault et une liste double-liée corrompue, parce que selon ma compréhension, du point de vue de la glibc ils devraient ressembler à la même chose. Parce que si j'implémente une liste double-liée à l'intérieur de mon programme, comment la glibc pourrait-elle savoir qu'il s'agit d'une liste double-liée, au lieu de n'importe quelle autre structure? Ça ne peut probablement pas, alors c'est pour ça que j'étais confus.
Maintenant, j'ai regardé malloc/malloc.c à l'intérieur de la glibc code, et je vois le suivant:
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; \
alors maintenant cela prend tout à coup un sens. La raison pour laquelle glibc peut savoir qu'il s'agit d'une liste double-liée est que la liste fait partie de glibc lui-même. J'ai été confus parce que je pensais que glibc pouvait d'une façon ou d'une autre détecter qu'une certaine programmation est en train de construire une liste double-liée, ce que je ne comprendrais pas comment cela fonctionne. Mais si cette liste double-liée qu'il parle environ, fait partie de glibc lui-même, bien sûr, il peut savoir que c'est une liste double-liée.
je ne sais toujours pas ce qui a provoqué cette erreur. Mais au moins je comprends la différence entre une liste double-liée corrompue et une Segfault, et comment la glibc peut savoir que cette structure est supposée être une liste double-liée:)
débordement de Tas devrait être responsables (mais pas toujours) pour corrupted double-linked list
,malloc(): memory corruption
,double free or corruption (!prev)
- comme les Avertissements glibc.
Il doit être reproduite par le code suivant:
#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;
}
si compilé à l'aide de 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
et si compilé à l'aide de clang++(6.0 (clang-600.0.56)):
$ ./heapoverflow
[1] 96277 segmentation fault ./heapoverflow
si vous pensez avoir écrit un bug comme celui-ci, voici quelques conseils pour le tracer.
Première, compiler le code avec le drapeau de debug(-g
):
g++ -g foo.cpp
et ensuite, lancez-le avec 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)
Le bug est situé dans ==12693== à 0x400A25: main (foo.rpc:11)
pour tous ceux qui cherchent des solutions ici, j'ai eu un problème similaire avec C++: malloc (): smallbin liste double liée corrompue:
Ceci était dû à une fonction ne retourne pas une valeur, il était censé.
std::vector<Object> generateStuff(std::vector<Object>& target> {
std::vector<Object> returnValue;
editStuff(target);
// RETURN MISSING
}
Je ne sais pas pourquoi cela a pu être compilé après tout. Probablement il y avait un avertissement à ce sujet.
cela peut causer par différentes raisons, certains ont dit d'autres candidats et je vais présenter mon cas:
j'ai eu cette erreur en utilisant le multi-threading (les deux std::pthread
et std::thread
) et l'erreur s'est produite parce que j'ai oublié de verrouiller une variable qui multi-threads peuvent changer en même temps.
cette erreur vient au hasard dans certaines courses, mais pas tout parce que ... tu sais que l'accident entre les fils est aléatoire.
Cette variable dans mon cas était un mondial std::vector
j'ai essayé de push_back()
quelque chose dans une fonction appelée par les threads.. et ensuite, j'ai utilisé un std::mutex
et n'a jamais eu cette erreur à nouveau.
peut aider certains
j'ai rencontré cette erreur dans un code où quelqu'un appelait exit() dans un thread à peu près en même temps que main()
retourné, de sorte que tous les constructeurs globaux/statiques ont été lancés dans deux threads séparés simultanément.
Cette erreur se manifeste aussi que double free or corruption
, ou un segfault / sig11 inside exit()
ou
#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[] (...)
(...)
Je n'ai pas pu le faire montrer ce problème en courant sous valgrind.