gcc: "double free or corruption" - Megoldva

Fórumok

Sziasztok!

Csinálok egy elég egyszerű programot és ezt a hibaüzenetet kaptam:


*** glibc detected *** double free or corruption (out): 0x081370b8 ***

Ez mitől lehet?
Valahol a netetn azt találtam, hogy ha ezt használom, akkor megjavul:


export MALLOC_CHECK_=0

De nem működik. Mi lehet szerintetek a gond? Találkozott már valaki hasonlóval?

Üdv:
denx

Hozzászólások

#include <stdlib.h>
int main()
{
void *a= malloc (8);
free(a);
free(a);
return 0;
}

továbbá: Electric Fence, illetve szorgos debuggolás: addig egyszerűsítjük a programot, amíg meg nem szűnik a hiba; az utoljára kivett rész okozta a gondot, vagy legalábbis köze volt hozzá.
Az ellenőrzés letiltása (MALLOC_CHECK) természetesen nem megoldás.

#include <stdlib.h>
int main()
{
size_t *a=(size_t*) malloc (8);
a[-1]=(size_t)a;
a=(size_t*) realloc(a,0);
return 0;
}

Másik kód ami, előidézheti.

ha kicsit bonyolultabb a program/algoritmus, akkor mar annyira nem egyszeru a felszabaditas.. lama dolog ugyan, de tobbek kozt ezert terjednek annyira a garbage collector-os nyelvek (.net, java, scriptnyelvek)
az meg, hogy egy tombbol kiindexel, szinten szokasos, es sulyos hiba, es el szoktak kovetni.. eleg rakeresni a buffer overrun exploitokra.. ha raadasul stack-en van, akkor meg konnyen ki is lehet hasznalni betoresre..
---------------------
"A feny azt hiszi, gyorsabb mindennel, de teved. Mindegy, milyen sebesen szaguld a feny, mindig azt fogja talalni a vegen, hogy a sotetseg ert oda elsonek, es ra var." - Terry Pratchett

Háhááá csak a garbage collector azellennemvéd. Ha valahol véletlenül megmarad a referencia az ovjektumra, akkor a gc nem tudja kihajítani és frankó memory leakeket lehet gyártani vele. (Lásd még: "Miért zabálják a memóriát a java-s programok?") Tény, hogy talán a problémák egy részét kiszűri a gc, de messze nem csodaszer. A java profiling viszont jó kis játék... jó sok időt el lehet vele tölteni és közben jó sok hajat tépni, mire megtalálja az ember, hogy valami bonyolultabb rekurzív algoritums lekódolásának hevében melyik változót felejtette el null-ra állítani. Plusz pontért más ember által írt kódban ugyanezt. :)
---
Keep on trolling

Csak érdekesség képpen :-)
Én Knoppix leszármazott LiveCD-ről bootolva próbáltam partimage-gel backupot csinálni. kb 80%-nál a partimage pontosan ezzel a hibaüzenettel szállt el.

mennyire bonyolult/hosszu a program?
---------------------
"A feny azt hiszi, gyorsabb mindennel, de teved. Mindegy, milyen sebesen szaguld a feny, mindig azt fogja talalni a vegen, hogy a sotetseg ert oda elsonek, es ra var." - Terry Pratchett

Most kezd bonyolódni. Amúgy elég egyszerű a dolog és látszólag értelmetlen helyen akad ki. Sőt! Ha egy másik értelmetlen helyen feltöltöm a frissen allokált memóriát speciális értékekkel (-1) akkor kezd csak kiakadni!

Tanácstalan vagyok. Nem sok kedvemn van az egészet átnézni, de félek tőle, csak az marad!

Biztos elegendő memóriát foglalsz? Nem felejtetted el megszorozni pl. egy sizeof(int) -el, 0 tol indexeled?.(Ne vedd sértésnek)

Nagyon valószínű, hogy valhol rosszul indexelsz pl. tömböt, és olyan helyre írsz ahhol malloc a memoria allokációs adatait tárolja.

Ha nem túl nagy a kód és nem túl bizalmas, akkor be is postolhatnád.
vagy pl. http://pastebin.com/ -en elhelyezhetnéd.

Nemrég nekem is hasonlókat üzengetett (talán a 3.3-as fölötti gcc-vel, azt hiszem)
A g_free()-k helyett g_object_unref()-el szabadítottam fel a glib függvényei által foglalt területeket...

foditsd debug modban, -g, valgrind (, gdb, strace).

ultra egy fos amit kikopnek, de erdemes atnezni es okulni belole. ha nem vilagos, akkor olvasni mig az nem lesz .... vagy atterni C# v. java-ra.

Mindenkinek köszönöm a segítséget! Valgrind volt a megoldás!

Az eset nem volt annyira egyszerű, de megoldottam. Mindenki okulására itt a lényeg:


#define T_SIZE 20

typedef struct t2{
    char c;
    int i;
} t2_t;

typedef t2_t t1_t[T_SIZE];

/*...*/

t1_t *func(){
    t1_t *res = calloc(sizeof(t1_t),1);
    int j;
    for(j=0;j<T_SIZE;j++){
        res[j]->c='\1';
        res[j]->i=-1;
    }
    return res;
}

Kijavítva:


/*...*/

t1_t *func(){
    t1_t res;
    int j;
    for(j=0;j<T_SIZE;j++){
        res[j].c='\1';
        res[j].i=-1;
    }
    return &res;
}

Üdv:
denx

UI: Lehet a fenti kódban van hiba, de igyekeztem csak a lényeget kicserélni

ansi c permits mixed code and declarations, vagy hogy is mondja. illendő betartani

t1_t *res=NULL
...

res=calloc(sizeof(t1_t),1);
...
return res;

SZVSZ így mennie kéne. első glancra. vagy az indexelés (de azt most este meg sem próbáltam felfogni. egész nap fizikáztam.)

Nem hagytál edittálni:


t1_t *func(){
        t2_t *res = calloc(sizeof(t1_t),1);
        int j;
        for(j=0;j<T_SIZE;j++){
                res[j].c='\1';
                res[j].i=-1;
        }
        return (t1_t*)res;
}

Ha nem rontottam el.

szerk: Elbandi callockja lehet, hogy szebb , de ide malloc is jó mivel úgy is a ciklusban kap értéket.

szerk2: Ha nem suliba készül,ezt az ősi szabvány-t nem fontos betartani, nem ismerek olyan fordítót ami nem támogatná.
------
gentóhuszár

Gyerekek ti mind nagyon fáradtak vagytok. :)

denx, te kijavítottál egy hibát, és beraktál egy másikat. :)

A calloc kell (vagy inkább malloc) mert különben a lokális változót turkálod, ami visszatéréskor "eltűnik". Persze ez akkor tűnik fel, mikor egy következő fv hívás felülírja a vermet.

Viszont ügyesen észrevetted, hogy "res[j]->c" helyett "res[j].c" kell.
(Perverzeknek "(res+j)->c").

(Egyébként a struct mögé nem kell a t2.)

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

Ezt majdnem odaírtam én is, de aztán mégse, elvégre a "->"-at kb így szokták bevezetni a könyvekben. :)

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

Persze. Ő írta be, igaz 2 részletben. :)
Látom fáradtak vagytok, pedig csak most kezdődik az éjszaka.


/*...*/

t1_t* func(){
    t1_t *res;
    int j;
    res=(t1_t*) calloc(sizeof(t1_t),1);

    for(j=0;j<T_SIZE;j++){
        res[j].c='\1';
        res[j].i=-1;
    }
    return res;
}

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

In function 'func':
error: request for member 'c' in something not a structure or union
error: request for member 'i' in something not a structure or union

Nem figyelsz, faradt vagy!
Mondom tipus!


t1_t* func(){
        t1_t *res;
        int j;
        res=(t1_t*) calloc(sizeof(t1_t),1);

        for(j=0;j<T_SIZE;j++){
                (*res)[j].c='\1';
                (*res)[j].i=-1;
        }
        return res;
}

------
gentóhuszár

Oh my God!

Mentségemre legyen mondva 4-5 éve nem írtam C-ben semmit.
Ilyen kódot meg soha... Ezek a typedefek brrrr.

Akkor legyen inkább:


t2_t* func(){
    t2_t *res;
    int j;
    res=(t2_t*) calloc(sizeof(t2_t),T_SIZE);

    for(j=0;j<T_SIZE;j++){
        res[j].c='\1';
        res[j].i=-1;
    }
    return res;
}

Ez így talán a legkevésbé undorító leginkább C-s.

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

Gyors javítás:


t1_t *func (void)
{
    t1_t *res = calloc(sizeof(t1_t),1);
    int j;
    for(j=0;j<T_SIZE;j++){
        (*res)[j].c='\1';
        (*res)[j].i=-1;
    }
    return res;
}

Igényes javítás:


typedef struct telem {
    char c;
    int i;
} telem;

typedef struct tstruct {
    telem v[T_SIZE];
} tstruct;

tstruct *func (void)
{
    tstruct *res = calloc (sizeof (tstruct), 1);
    int j;

    for (j=0; j<T_SIZE; j++) {
        res->v[j].c='\1';
        res->v[j].i=-1;
    }
    return res;
}

Magyarul: lehetőleg ne használjunk összetett típusnak egy puszta tömböt, hanem ágyazzuk be egy struktúrába, például azért, hogy a fordító észrevegye az ilyesfajta hibákat.