Toon posts:

[C++]free() zorgt voor execption

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb een variable array, maar op het moment dat ik het geheugen weer vrij wil geven met free() crasht mn programma. Dit zijn de relevante stukken code:

C++:
1
2
3
4
5
6
7
8
9
10
    gamedata.screenBuff = (CHAR_INFO*)malloc(sizeof(CHAR_INFO) * gamedata.width * gamedata.heigth);
    if(gamedata.screenBuff == NULL)
    {
        cout<<"Something went wrong";
    }
    for(int i=0; i<(sizeof(CHAR_INFO) * gamedata.width * gamedata.heigth); i++)
    {
        gamedata.screenBuff[i].Char.AsciiChar = ' ';
        gamedata.screenBuff[i].Attributes = BACKGROUND_GREEN;
    }


C++:
1
2
3
4
5
6
    while(!gamedata.gameover)
    {
        updateMove();
    }
    
    FreeMem();


C++:
1
2
3
4
5
6
7
8
9
10
11
void FreeMem()
{
    if(gamedata.screenBuff)
    {
        free(gamedata.screenBuff);
        gamedata.screenBuff = NULL;
    }

    FlushConsoleInputBuffer(gamedata.inputHandle); 
    
}


Ik ben al nu al ruim 3 uur bezig met debuggen, maar kom geen meter verder dan dat ie crash bij call free()

code:
1
2
3
4
5
00401B1E   mov         ecx,dword ptr [ebp+8]
00401B21   mov         edx,dword ptr [ecx]
00401B23   push        edx
00401B24   call        free (0040a4b0)
00401B29   add         esp,4

Afbeeldingslocatie: http://members.lycos.nl/hendre/memleak.jpg
(ik weet voor de rest vrij weinig van asm) O-)

[ Voor 4% gewijzigd door Verwijderd op 09-01-2005 21:47 ]


  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Ik ben niet echt een expert maar zou je geen 'new' en 'delete []' gebruiken?
Ziet er in elk geval beter uit en ik heb er nog nooit problemen mee gehad. malloc() en free() stamt volgens mij uit de C zonder ++ tijd (antiek :D).
Maar nu ik erover nadenk, ik denk dat 'new' wordt vervangen door 'malloc' tijdens compilen. Naja, proberen kan altijd :)dan wordt:
C++:
1
gamedata.screenBuff = (CHAR_INFO*)malloc(sizeof(CHAR_INFO) * gamedata.width * gamedata.heigth);

dit:
C++:
1
gamedata.screenBuff = new CHAR_INFO[gamedata.width * gamedata.heigth];


en dit:
C++:
1
2
3
4
5
if(gamedata.screenBuff) 
    { 
        free(gamedata.screenBuff); 
        gamedata.screenBuff = NULL; 
    }

wordt dan:
C++:
1
2
3
4
5
if(gamedata.screenBuff) 
    { 
        delete [] gamedata.screenBuff;
        gamedata.screenBuff = NULL; 
    }

[ Voor 21% gewijzigd door MLM op 09-01-2005 22:15 ]

-niks-


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

In die loop, multiply je met sizeof(CHAR_INFO) bij 'i'. Maar dat hoeft niet, want dat gebeurt al bij je index buffer[i], dat is hetzelfde als *((char*)(buffer) + i*sizeof(CHAR_INFO)). Maw, hier komt je damaged block door, als je die "i < sizeof(CHAR_INFO) * width * height" veranderd in "i < width * height" zou het moeten werken.

Een paar punten nog, zoals boven, in C++ gebruik je (iha) 'new' en geen malloc. Je hoeft bij een free() niet op 'null' te checken voor je pointer, free() doet dit zelf al.

Het is height en niet heigth ;) (maar idd wel width)

Oh, en C++ casts gaan eigenlijk met static_cast en reinterpret_cast en consorten, niet meer met de prefix tussen haakjes. Dus reinterpret_cast<CHAR_INFO*>(malloc(...)); Maar met new/delete heb je dat niet nodig, omdat new al een juist type pointer retourneerd.

[ Voor 47% gewijzigd door Zoijar op 09-01-2005 22:55 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
"Damage after block" - dat is toch duidelijk? Dan heb je achter je block geschreven.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

waarom gebruik je trouwens geen standaard template voor dit soort functionaliteit (de standaard vector class lijkt me in dit geval zeer geschikt)? Deze classes zijn zeer efficient geschreven (achter de class gaat overigens gewoon een array schuil zoals jij ook gebruikt), je hoeft je alleen geen zorgen meer te maken over geheugenallocaties.

Sommigen denken dat het zelf gebruiken van een array efficienter is dan de standaard STL classes. Dit is (in het algemeen) NIET het geval. Wil je hierover meer lezen dan kun je bijvoorbeeld eens op google zoeken naar "C++ FAQ".

Verwijderd

Topicstarter
ok, thnx Zoijar het kwad idd door het vermenigvuldige met sizeof(). En heb ook malloc en free vervangen door resp. new en delete.

@Zoijar
ik ben nog niet zo bekend met vectoren, maar thnx voor je idee, ik zal er zeker naar kijken en kijken of ik het kan verbeteren/aanpassen :)

en MLM, bedankt voor je voorbeeld met new en delete [] :)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op maandag 10 januari 2005 @ 10:24:
Sommigen denken dat het zelf gebruiken van een array efficienter is dan de standaard STL classes. Dit is (in het algemeen) NIET het geval. Wil je hierover meer lezen dan kun je bijvoorbeeld eens op google zoeken naar "C++ FAQ".
Mwa, ik zou wel willen zeggen dat het iha wel het geval is, maar dat dit iha niet zo veel uitmaakt. Een geval van premature optimization. Maar bv zelf een geoptimaliseerde structuur schrijven om een vertex list, of triangle strip oid in te genereren, elke frame, van behoorlijke grootte, dat scheelt enorm met een std::vector.

Verwijderd

Mwa, ik zou wel willen zeggen dat het iha wel het geval is, maar dat dit iha niet zo veel uitmaakt. Een geval van premature optimization. Maar bv zelf een geoptimaliseerde structuur schrijven om een vertex list, of triangle strip oid in te genereren, elke frame, van behoorlijke grootte, dat scheelt enorm met een std::vector.
Als je SGI's STL documentatie leest, zul je zien dat de eisen die gesteld worden aan de performance van abstracte containers niet verschillen van wat je van een C-style array verwacht. Hoogstens kan het zo zijn dat je een container wilt gebruiken die andere functionaliteit biedt (zoals bijv. een list als je veel elementen middenin je blok wil invoegen, of een hashtable, of een tree), maar daarvoor zou je normaal gesproken ook geen array willen gebruiken.

In het algemeen is het zeer onwaarschijnlijk dat je zelf in staat bent om eventjes een wrapper class voor een array in elkaar te knutselen die efficienter is dan wat er door de STL geboden wordt (moet je natuurlijk wel een goede STL implementatie gebruiken...)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op maandag 10 januari 2005 @ 12:38:
Als je SGI's STL documentatie leest, zul je zien dat de eisen die gesteld worden aan de performance van abstracte containers niet verschillen van wat je van een C-style array verwacht. Hoogstens kan het zo zijn dat je een container wilt gebruiken die andere functionaliteit biedt (zoals bijv. een list als je veel elementen middenin je blok wil invoegen, of een hashtable, of een tree), maar daarvoor zou je normaal gesproken ook geen array willen gebruiken.

In het algemeen is het zeer onwaarschijnlijk dat je zelf in staat bent om eventjes een wrapper class voor een array in elkaar te knutselen die efficienter is dan wat er door de STL geboden wordt (moet je natuurlijk wel een goede STL implementatie gebruiken...)
Toch blijkt m'n eigen DynamicArray, die in gebruik hetzelfde is als een std::vector (op wat iterator/algorithm links na), aanzienlijk sneller. Ik heb frame rates van 10 naar 30 fps oid zien gaan, door het vervangen van een typedef naar m'n eigen class. Maar dit zijn wel uitzonderlijke gevallen, waar het besparen van een paar instructies groten gevolgen heeft. Iha, zal dat niet zoveel uitmaken, en is de duidelijkheid en robuustheid die je wint met std::vector, veel belangrijker.

  • Jrz
  • Registratie: Mei 2000
  • Laatst online: 09:58

Jrz

––––––––––––

C:
1
2
3
4
5
for(int i=0; i<(sizeof(CHAR_INFO) * gamedata.width * gamedata.heigth); i++) 
    { 
        gamedata.screenBuff[i].Char.AsciiChar = ' '; 
        gamedata.screenBuff[i].Attributes = BACKGROUND_GREEN; 
    }


je hebt een buffer overflow.

C:
1
for(int i=0; i< gamedata.width * gamedata.heigth; i++) 


lijkt me beter.

[ Voor 10% gewijzigd door Jrz op 10-01-2005 12:56 ]

Ennnnnnnnnn laat losssssssss.... https://github.com/jrz/container-shell (instant container met chroot op current directory)


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

spuit 11? ;) hehe

Verwijderd

precies. Natuurlijk zijn er altijd uitzonderingsgevallen waarbij het wel zinvol is om je eigen implementatie te maken. Doorgaans is dit echter niet het geval. Wat betreft het bericht waarmee dit topic begon: gebruik van free() en malloc() en C-style arrays waar een vector ook kan voldoen getuigt niet bepaald van kennis en kundigheid betreffende C++.

Voor de originele poster de volgende tip:
[url]http://http://www.parashift.com/c++-faq-lite/index.html[/url]

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:44

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op maandag 10 januari 2005 @ 12:38:
In het algemeen is het zeer onwaarschijnlijk dat je zelf in staat bent om eventjes een wrapper class voor een array in elkaar te knutselen die efficienter is dan wat er door de STL geboden wordt (moet je natuurlijk wel een goede STL implementatie gebruiken...)
Wat natuurlijk onzin is, een vector is gewoon een array met wat dynamische groei-functionaliteit, en door gebruik van inline functions en een goede optimaliserende compiler is vector-acces exact hetzelfde als normale array-access, en dat kun je met eigen wrapper classes ook wel bereiken (de vraag is dan alleen of je dat ook wilt aangezien std::vector al bestaat ;)).

Voor de andere containers is het een ander verhaal, die gebruiken andere structuren, en het is goed mogelijk dat de structuur die voor jou het efficientst werkt niet geboden wordt door de STL, waardoor je dus een eigen class moet schrijven. Zo had ik onlangs een snelle random access structuur nodig waaraan ik efficient aan het eind elementen kon toevoegen. Een vector heeft natuurlijk een snelle random access tijd, maar vereist een contiguous memory block waardoor eens in de zoveel tijd de hele array gekopieerd wordt. Als je daar objecten in stopt met een dure copy ctor dan heeft dat een behoorlijke performance hit. De deque is in dit geval de beste keuze uit de STL, maar die gebruikt een map om een lookup te doen voor de juiste buffer bij een bepaalde index waar ik niet zo heel erg blij mee was. Ik heb toen een container gemaakt die losse buffers alloceert van een vaste grootte (macht van 2 bovendien) en die in een vector plaatst, zodat ik mbv een shift en een and op de index in constante tijd en weinig cycles het juiste element kan vinden. Een push_back is relatief goedkoop; als de laatste buffer nog niet gevuld is dan kost het niets (anders dan een copy ctor natuurlijk), zo wel dan wordt er een push_back gedaan op een std::vector<T*>, die ook relatief goedkoop is.

Bottom line is dat de STL generiek is en performance eissen nou juist specifiek zijn. Mijn ervaring is dat als je echt met serieuze optimalisaties bezig bent waar elke cycle telt je bijna altijd beter af bent met een container die specifiek voor die taak is ontworpen.

.edit: beetje spuit 11 inmiddels ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Wat natuurlijk onzin is, een vector is gewoon een array met wat dynamische groei-functionaliteit, en door gebruik van inline functions en een goede optimaliserende compiler is vector-acces exact hetzelfde als normale array-access, en dat kun je met eigen wrapper classes ook wel bereiken (de vraag is dan alleen of je dat ook wilt aangezien std::vector al bestaat ;)).
Je zegt precies hetzelfde als ik: er is geen echt efficientieverschil tussen C-style arrays en std::vector. Om een efficientere container zelf te implementeren, moet je dus nogal wat moeite doen. Ik zie niet in waarom mijn opmerking dan onzin zou zijn en de jouwe niet. Volgens mij zijn we het nl. gewoon eens :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:44

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ah idd dan begreep ik je verkeerd, je zei namelijk dat je "geen betere" implementatie kan schrijven dan die van std::vector, wat ik opvatte als dat het moeilijk is om een container te schrijven die std::vector evenaart, wat niet echt het geval is :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1