Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[C++] new/malloc werkt na een tijd niet meer

Pagina: 1
Acties:

  • Dragon
  • Registratie: Oktober 2002
  • Laatst online: 20-10 12:05
Ik heb een probleem met de functie new (die in feite malloc gebruikt). Mijn applicatie loopt altijd vast op een bepaalde new in de code. Bij deze new/malloc wijs ik een nieuwe blok geheugen toe voor gegevens die in een struct komen, deze struct wordt vaker gebruikt en dit is ongeveer de achtste keer dat malloc gebruikt wordt voor dezelfde struct.

Na het bekijken van de debugger zie ik dat hij de ENOMEM fout krijgt tijdens het aanroepen van de HeapAlloc API. Echter als ik een release build maak en ik voer de code uit dan werkt dit zonder problemen. De applicatie gebruikt overigens ca 7,5MB RAM op het moment van de crash en ik kan geen memory leaks vinden die dit zouden kunnen veroorzaken.

Ik heb al een tijd lopen zoeken naar een oorzaak (en oplossing) voor dit probleem, is er iemand bekend met di t fenomeen?

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:54
Heb je misschien last van heap fragmentatie?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Sappie
  • Registratie: September 2000
  • Laatst online: 01-11 23:46

Sappie

De Parasitaire Capaciteit!

Debug je programma eens met een memory debugger zoals bijvoorbeeld valgrind. Verder, laat eens wat code zien, kunnen we ook zien wat er gebeurt.

Specs | Audioscrobbler


  • Dragon
  • Registratie: Oktober 2002
  • Laatst online: 20-10 12:05
Misschien maar ik weet eigenlijk niet hoeveel ik precies tot mijn beschikking heb. Dit zijn in ieder geval de allocations/deallocations, zoals te zien gaan de laatste 3 mis.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Allocated       0x01f470a8      28 bytes
Allocated       0x01f48140      128 bytes
Allocated       0x01f48870      12 bytes
Allocated       0x01f48908      28 bytes
Allocated       0x01f489b0      28 bytes
Allocated       0x01f48a58      28 bytes
Allocated       0x01f48b10      4 bytes
Allocated       0x01f48b50      8 bytes
Deallocated     0x01f48b10
Allocated       0x01f48b10      4 bytes
Allocated       0x01f48b98      8 bytes
Allocated       0x01f48ee8      600 bytes
Deallocated     0x01f48b10
Allocated       0x01f493d0      600 bytes
Allocated       0x01f49668      8 bytes
Allocated       0x01f496b0      12 bytes
Allocated       0x01f48b10      4 bytes
Allocated       0x01f496f8      8 bytes
Allocated       0x01f49990      176 bytes
Allocated       0x01f49a80      1140 bytes
Allocated       0x01f49f30      8 bytes
Allocated       0x01f48b10      4 bytes
Allocated       0x01f49f78      16 bytes
Allocated       0x01f49fc8      8 bytes
Allocated       0x01f4a010      32 bytes
Allocated       0x01f4a070      16 bytes
Allocated       0x01f4a0c0      4 bytes
Deallocated     0x01f4a070
Deallocated     0x01f4a010
Deallocated     0x01f4a0c0
Deallocated     0x01f49fc8
Deallocated     0x01f49f78
Deallocated     0x01f48b10
Deallocated     0x01f49f30
Allocated       0x01f49f30      8 bytes
Allocated       0x01f48b10      4 bytes
Allocated       0x01f49f78      144 bytes
Allocated       0x01f4a160      128 bytes
Allocated       0x01f4a048      78 bytes
Allocated       0x01f4a8d8      8 bytes
Allocated       0x01f4a638      94 bytes
Allocated       0x01f4a6d8      78 bytes
Allocated       0x01f4a9d8      4 bytes
Deallocated     0x01f4a6d8
Deallocated     0x01f4a638
Deallocated     0x01f4a9d8
Deallocated     0x01f4a8d8
Deallocated     0x01f4a048
Deallocated     0x01f4a160
Deallocated     0x01f49f78
Deallocated     0x01f48b10
Deallocated     0x01f49f30
Allocated       0x01f4a8d8      8 bytes
Allocated       0x01f48b10      4 bytes
Allocated       0x01f4a9d8      16 bytes
Allocated       0x01f4a160      75 bytes
Allocated       0x00000000      8 bytes
Allocated       0x00000000      91 bytes
Allocated       0x00000000      75 bytes

  • alx
  • Registratie: Maart 2002
  • Niet online

alx

Kan aan allerlei dingen liggen. Idd heap fragm, leaks, maar ook heap corruption (of brk()/mmap() blocks of echt out-of-mem, beide onwaarsch). Kun je niet een zwaar debuggende malloc variant proberen of in valgrind runnen? Als heap corruption moet je fast-failure proberen te triggeren.

  • Dragon
  • Registratie: Oktober 2002
  • Laatst online: 20-10 12:05
Code die new gebruikt, deze gaat dus ca 7x wel goed:
code:
1
2
3
 packet* recvPacket = new packet;
 <code>
 delete recvPacket;


De struct:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */

struct packet
{
    BYTE lenStream;
    WORD msgCount;  
        ...

        operator char*()
        {
           code
        }
         
         <meer methodes voor conversie naar een pakket (voor netwerken)>
}

Dit gebeurd in een thread gemaakt met CreateThread() en ik gebruik MSVS2008.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14-11 23:57

.oisyn

Moderator Devschuur®

Demotivational Speaker

Lekker handig, Valgrind suggereren terwijl hij op Windows runt ;)

Maar idd, waarschijnlijk is het heap corruption, veroorzaakt door een van de volgende punten:
- Je dealloceert een pointer die je niet hebt gealloceert
- Je dealloceert een pointer die je hebt vrijgegeven
- Je schrijft buiten de gealloceerde buffer.
- Je schrijft naar geheugen dat nooit is gealloceerd / al is vrijgegeven.

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Het is wel raar dat het in debug crashed maar niet in release, meestal is het andersom. Maar dat kan komen doordat je debug build je ongebruikte geheugen initialiseert met 0xDEADBEEF oid, en is een release build het gewoon allemaal nullen zijn. Als je zo'n pointer delete bv dan gaat het in een release build gewoon goed, want je mag een null pointer deleten.

Anders geheugen monitoren in de VC debugger. Vervelende bugs. Sloop er steeds meer functionaliteit uit totdat je op de kern stuit.

offtopic:
zit ik in bordeaux en dan alsnog alleen op m'n hotelkamer C++ probleempjes te kijken... te moe om uit te gaan, ik word oud... hehe

[ Voor 12% gewijzigd door Zoijar op 26-10-2008 21:46 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Er klopt iets ernstig niet, als new een null-pointer teruggeeft. new gooit een exception, als er geen memory meer is. (VS6 had een bekende bug hier, VS2008 niet.)

En ik gok dat je crash het gevolg is van het gebruiken van die null-pointer?

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


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 23:49

Reptile209

- gers -

Wat de oorzaak is weet ik niet, maar er zit iets geks in je tabel met Allocs en Deallocs (Dragon in "\[C++] new/malloc werkt na een tijd niet ..."). In regel 17 en 22 gebruik je hetzelfde adres, zonder dat dat tussendoor vrijgegeven is. * Reptile209 heeft even wat zitten sorteren in Excel (*).
Zoals gezegd: het is een symptoom, niet de oorzaak. Misschien helpt het om te achterhalen wat er wel gebeurt. Ik neem aan dat vanaf regel 22 je geheugenbeheer naar de spreekwoordelijke rag is, en dat het geluk is dat het nog zo lang goed gaat.

Happy debugging ;)

(*) Regelnummertjes ervoor zetten, dan de hele tabel sorteren op Address en dan op volgnummer. Dan zie je tussen het blok met address 0x01f48b10 opeens twee allocs onder elkaar staan op hetzelfde adres

[ Voor 15% gewijzigd door Reptile209 op 27-10-2008 20:54 ]

Zo scherp als een voetbal!


Verwijderd

Is er niet een equivalent voor Valgrind in Windows? Dat is echt zo'n tool waarmee je dit soort fouten in 5 seconden gevonden hebt.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

boundschecker

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14-11 23:57

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wikipedia: Memory debugger
Overigens kun je ook wel het een en ander met de standaard CRT libraries. Zoals _crtSetDbgFlag() met de _CRTDBG_CHECK_ALWAYS_DF flag om bij elke allocatie en deallocatie een heap consistency check te doen. Op het moment dat die een fout aangeeft weet je dus dat tussen de vorige alloc/dealloc en de huidige de fout optreedt. Verder kun je met _CrtCheckMemory() zelf een consistency check uitvoeren waarmee je de plek van de fout verder kunt isoleren.

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.


  • Toolmaker
  • Registratie: April 2004
  • Laatst online: 09-06 16:59
Zoijar schreef op zondag 26 oktober 2008 @ 21:38:
Het is wel raar dat het in debug crashed maar niet in release, meestal is het andersom. Maar dat kan komen doordat je debug build je ongebruikte geheugen initialiseert met 0xDEADBEEF oid, en is een release build het gewoon allemaal nullen zijn. Als je zo'n pointer delete bv dan gaat het in een release build gewoon goed, want je mag een null pointer deleten.

Anders geheugen monitoren in de VC debugger. Vervelende bugs. Sloop er steeds meer functionaliteit uit totdat je op de kern stuit.

offtopic:
zit ik in bordeaux en dan alsnog alleen op m'n hotelkamer C++ probleempjes te kijken... te moe om uit te gaan, ik word oud... hehe
Dit is niet helemaal correct... new gooit een exception op het moment dat hij geen geheugen kan alloceren, en niet 0x0000000. Daarnaast wordt het geheugen in release mode niet geinitaliseerd. Het bevat gewoon wat er op dat moment in staat.

VC bewerkt geheugen met diverse adreswaarden voor, tijdens en na allocaties, inclusief memory guards voor en na het geheugen. Als je in release een delete doet, dan wordt je pointer niet op NULL gezet. Wat je zou kunnen doen is een SAFE_DELETE() macro maken die een pointer delete en vervolgens op NULL zet. Wat bevat je geheugen adres op het moment dat die crash optreedt?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

ik heb het helemaal niet over new in mijn post :)
Pagina: 1