"corrupted double-linked list": glibc hibaüzenet

 ( horvatha | 2008. március 3., hétfő - 12:24 )

Kedves HUP-osok!

Egy számomra misztikus hibába futottam bele C progi dinamikus memóriakezelése kapcsán.

Van egy kis struct-om, mely tartalmaz pointereket is és meg is írtam ehhez a szükséges alloc-free rutinkákat, meg realloc-os méretnövelőket. Eleinte úgy tűnt, szépen fut is.

Most azonban misztikusan elhalálozik ilyen üzenetet dobva:

..................
*** glibc detected *** /home/horvatha/....(végrehajtható fájl neve): corrupted double-linked list: 0x08056548 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7e2c37d]
/lib/tls/i686/cmov/libc.so.6[0xb7e2e1bd]
/lib/tls/i686/cmov/libc.so.6(__libc_malloc+0x90)[0xb7e2ffc0]
/lib/tls/i686/cmov/libc.so.6(realloc+0x1d5)[0xb7e31b35]
..................

A program úgy néz ki, hogy a main hív egy függvényt, amin belül lokális változó egy ilyen struct, dinamikusan létrehozom, dolgozok vele, megszüntetem a végén.

Ami misztikus: a main-ből egyszer meghívva a függvényt, minden jól megy. A második hívásnál hasal el, pedig ugye a lokális változó még akkor sem őrizne meg semmit a múltból, ha nem jó lenne a felszabadítási rutin az első hívás végén.

Debug-olva az látszik, hogy egy olyan realloc() hívás okozza a bajt, melynél az első argumentumba NULL kerül: de a doksi szerint ez egy malloc()-cal egyenértékű. A fenti "Backtrace" is ezt mutatja.

Hol keresgéljem a hibát? Mi okozhat ilyet: másodszor meghívott függvény lokális változójával kapcsolatos a hiba.

(Természetesen a két hívás argumentumait cserélgettem: mindig a 2. hívás okozott hibát....)

Előre is köszi! Biztos triviális, csak bamba vagyok....

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Forrás sokat segítene...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

tipikusan akkor szokott ilyen előfordulni, ha kétszer szabadítasz fel egy objektumot: a második hívás tönkreteszi a heap-et, de ez csak a következő allokációkor derül ki.

Javasolt:
- felszabadított pointereket azonnal kinullázni!
- shared pointereket használni
- assert-eket nagyon bőven használni

Vigyázni kell ilyenkor a debuggerrel is, nekem már volt olyan, hogy a függvény látszólag helyes paraméterekkel hívódik meg, de mégis ott hal meg a program. De ilyenkor nem a könyvtári függvénnyel van a baj, szinte biztos, hogy dinamikus memóriakezelési hiba, aminek a hatása viszont csak később jön elő. Én ellenőrizném az összes malloc/calloc/realloc argumentumait.

"dinamikus memóriakezelési hiba, aminek a hatása viszont csak később jön elő"

Ez a megoldás! Köszi!

Egész máshol szúrtam el malloc-ot és itt csapta ki a biztosítékot, mert itt zavarodott össze. Ez az utasítás tényleg érvényes volt. (Ezt a részt korábban már agyonteszteltem, azért nem értettem, hogy akad ki itt a progi. De már látom és megtanultam, hogy a glibc néha ellenőriz és csak akkor szól, ami lehet, hogy később van, mint a hibás utasítás.)

A valgrind egy pillanat alatt lebuktatta a bűnöst.

Most apache error.log-ban találtam én is ilyet:
*** glibc detected *** corrupted double-linked list: 0xb7ddb4f8 ***

Mitől lehetett ez? (Apache 1.3.34, PHP 4.4.4, Kernel 2.6.24-5, Debian Etch) Előtte még nem volt ilyen soha.

Cserelj apacsot. Regi.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Az rendben van, én is tudom hogy régi, de eddig nem volt ilyen probléma, most dobott csak először ilyet, és jobban érdekelne az hogy mitől lehetett ez, mint hogy upgradeljek aztán Apache2-vel is hasonlóba fussak. (Google találatok szerint Apache2+PHP5-tel is van akinek ugyan ez a hiba volt, és max annyit javasoltak nekik hogy a glibc-t upgradeljék vagy downgradeljék.)

Nem tudom, en tobb szerveren is uzemeltetek apacsot minden lathato problema nelkul. En elso korben biztos, hogy kulsoleg forditott apache/php modulra gyanakodnek, azutan konkretan magara az apacsra. Annak a kodjat azert ilyesmi ellen szinte biztos, hogy tesztelik.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

En is most szopok. Kis keresgeles utan a "libapache-mod-auth-mysql" a bunos. Jo ideje kiderult mar az osszes debian repobol, de most pakolok at masik gepre egy hosting szervert. Par csomag mar hianyzik az etch-bol, ami a regi gepen fent van. A vicc az, hogy ott nincs baja, ha (jobb hijan...) atmasolom, ldconfig, akkor https eseten ledoglik.

Alakul...Alighogy otthagytam a gepet, beugrott, hogy a normal konyvtar-hozzaferesek is sql-ben vannak, szoval vmiert csak https eseten hal le az apache child. Izgalmas lesz kitalalni, mi okozza...