[c++] memory leak

Pagina: 1
Acties:

  • KillerZero86
  • Registratie: Mei 2010
  • Laatst online: 12-07 23:09
Ik ben op dit moment bezig met een C++ project dat gebruikt maakt van Direct2D, KinectSDK en MFC. Hierin loop ik helaas tegen een hardnekkige memory leak aan. Om te beginnen: wat theorie over de software:

*snip*
Het programma begint in main.cpp. Deze initialiseerd de GUI en de kinectManager, deze objecten blijven bestaan tot de applicatie wordt gesloten. Verder wordt hierin ook het Kinectobject gebouwd. Deze bouwt op haar beurt alles op wat nodig is om het beeld uit de kinect te halen, te modificeren en op het scherm te brengen (NUI object, facetracking objecten, Direct2D objecten). Als dit object helemaal klaar is met haar initialisatie draait het programma stabiel en prima (geen constante memory leaks gelukkig). Het probleem is er wanneer er van kinect geswitched word: dan wordt het kinect object gedelete en deze destruct op haar beurt weer alles wat zij aan "kinderen" heeft (D2D, FT, enz.), zodat in theorie het programma terugvalt naar de staat vlak voor de initialisatie van de kinect. Hierna wordt een nieuw kinect object opgebouwd die weer alles onder zich op gaat bouwen enz.

Het is het deleten waarbij er kennelijk bepaalde objecten de destructieronde overleven en blijven bestaan, want na het aanmaken van het nieuwe Kinect object is er ongeveer 40 á 50 MB extra geheugen in gebruik.
Wat ik zelf al heb gedaan om het probleem te verhelpen:
-Ervoor gezorgd dat bij elk new keyword het object (de pointer) ook met het delete keyword te maken krijgt
-Alle D2D en Facetracking gerelateerde pointers middels Saferelease afgebroken (deze roept eerst Release() aan en zet de pointer dan op NULL).

Dit alles heeft het lek teruggebracht van rond de 120 MB naar rond de 45, maar nog niet helemaal opgelost.

Alle vormen van tips zijn welkom: onderzoekstechnieken, tutorials, directe tips (Je hebt object d aangemaakt met new, maar er daarna nooit delete op losgelaten!) etc.

Alvast bedankt!

[ Voor 2% gewijzigd door RobIII op 29-11-2012 15:55 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Je volledige code dumpen (of een link naar de volledige code) is niet de bedoeling hier; zie Kan iemand even...?.
Maak a.u.b. een kleine(!), uitgeklede(!), testcase die je probleem reproduceert met enkel de hoognodige relevante(!) code en post dat gewoon in je topic.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik zou eens naar iets als valgrind kijken, eventueel kan een statische code analyse tool ook al uitkomst bieden ( Lint bijvoorbeeld )

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • KillerZero86
  • Registratie: Mei 2010
  • Laatst online: 12-07 23:09
@robIII en wat nou als ik echt geen flauw idee heb waar ik moet gaan zoeken in de code? Ik weet gewoon niet waar de Memory Leak zit, het zou iedere globale pointer kunnen zijn in iedere methode waarin deze gebruikt word, wat erop neerkomt dat ik vrijwel alle code zou moeten dumpen. En dan nog kan ik er naast zitten en een hele rare structuur hebben gebouwd die ervoor zorgt dat een object dat geen pointer is een lifecycle heeft met de lengte van het programma.

@woy: bedankt voor de tip, ik ga ernaar kijken!

Anoniem: 221733

Valgrind is specifiek bedoeld voor Linux.
Voor windows applicaties heeft MS zelf functies ter beschiking.
MSDN: Memory Leak Detection and Isolation

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Moderne C++ code heeft eigenlijk geen 'new' of 'delete' meer nodig. Iets maken met ownership gaat via "std::make_shared<T>(...)". Alles dat je owned staat in een std::shared_ptr, en data passen doe je of via een normale pointer als er geen ownership overdracht is, of via een shared_ptr als beide ownership willen.

Ik raad je aan om alles via RAII te doen. Verreweg het belangrijkste paradigma in C++.

[ Voor 20% gewijzigd door Zoijar op 29-11-2012 17:01 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:51

.oisyn

Moderator Devschuur®

Demotivational Speaker

Anoniem: 221733 schreef op donderdag 29 november 2012 @ 16:35:
Valgrind is specifiek bedoeld voor Linux.
Voor windows applicaties heeft MS zelf functies ter beschiking.
MSDN: Memory Leak Detection and Isolation
Dit gaat je overigens niet zo heel goed helpen bij new/delete, want die tracken geen regel-informatie. Maar daar is wel wat voor te verzinnen:

C++:
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
__declspec(thread) const char * _currentFile = "<unknown>";
__declspec(thread) int _currentLine = 0;

void * operator new(size_t size)
{
    return _malloc_dbg(size,  _NORMAL_BLOCK, _currentFile, _currentLine);
}

void * operator new[](size_t size)
{
    return _malloc_dbg(size,  _NORMAL_BLOCK, _currentFile, _currentLine);
}

void operator delete(void * ptr)
{
   _free_dbg(ptr, _NORMAL_BLOCK);
}

void operator delete[](void * ptr)
{
   _free_dbg(ptr, _NORMAL_BLOCK);
}


#define TRACKING_NEW(x) ((_currentFile = __FILE__, _currentLine = __LINE__, new x))

En vervolgens doe je ipv new Foo(bar) gewoon TRACKING_NEW(Foo(bar)). Werkt ook met arrays.

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.


Acties:
  • 0 Henk 'm!

  • epic007
  • Registratie: Februari 2004
  • Laatst online: 26-06 16:56
Ik heb deze wel eens gebruikt:

http://vld.codeplex.com/

kwestie van een .lib en een .dll toevoegen aan je project.

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Wellicht overbodige tip, maar zorg er voor dat je op de goede momenten delete en delete [] gebruikt

Acties:
  • 0 Henk 'm!

  • KillerZero86
  • Registratie: Mei 2010
  • Laatst online: 12-07 23:09
Alle memory Leak reporters die ik gebruik schijnen het lek niet te zien: ik krijg er in totaal een memory leak van 10 kb uit en dan alleen via het programma wat epic007 mij aanraad. hieruit komen rond de 30 blokken die ieder een verwijzing hebben naar de f:\ schijf, welke ik niet heb. Kan iemand mij vertellen waarom? En wat het betekend dat zo'n programma het niet detecteerd?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:51

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat zullen wel gewoon CRT functies zijn die die memory allocaties hebben gedaan. De source daarvan is natuurlijk bij Microsoft gecompileerd en dus krijg je ook die paden te zien.

Maar ik ben wel benieuwd hoe je tot de conclusie bent gekomen dat er geheugen lekt.

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.


Acties:
  • 0 Henk 'm!

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

MLM

aka Zolo

De CRT doet ook wat heap allocaties, het is vrij normaal dat je een paar blokken overhoud aan het eind van je main() of WinMain() functies, die ga je niet "opgeruimd" krijgen, aangezien de clean-up daarvan (als die er al is) pas plaatst vind NADAT je programma klaar is met uitvoeren (als de MSVCXX.DLL vrijgegeven word). Op zich zou ik me geen zorgen maken over 10kb aan het eind van het programma.

De f:/ paden zijn van functies/code in de MSVCXX.DLL, dus die zijn sowieso een beetje ambigu in wat ze nou echt betekenen. Het kan alsnog een blok zijn dat gealloceerd werd adhv een library functie die je zelf aangeroepen hebt, waarvan de implementatie zich in de CRT bevind. Afhankelijk van je VC editie en versie heb je ook de CRT source-code meegeleverd gekregen en kan je gaan kijken op de aangegeven locaties (voor VS2010: <visual studio installatie>/VC/crt/src bijvoorbeeld)

-niks-


Acties:
  • 0 Henk 'm!

  • KillerZero86
  • Registratie: Mei 2010
  • Laatst online: 12-07 23:09
Via de Windows Taskmanager zie ik eht geheugenlek. Het programma gebruikt in eerste instante rond de 180 MB geheugen en als je dan van kinect wisselt is het 220-230 MB. En daarna 270-280 MB, enz.

Dus uit alle leakdumps blijkt feitelijk dat mijn code goed werkt en geen memoryleaks heeft. Waar wijst dat op? Dat ik ergens nog een referentie naar het geheugenadres van de pointer overhoud, waardoor de applicatie niet ziet dat het object feitelijk out of scope is en dat het dus vrijgegeven moet worden? Hoe controleer ik zo iets?

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Debuggen :) Log wanneer je een resource alloceert en vrij geeft, en kijk dan wat er gebeurt op de momenten dat je het geheugen gebruik omhoog ziet schieten. Het kan ook dat je driver lekt natuurlijk; daar kan je dan niks aan doen (bug report).

Acties:
  • 0 Henk 'm!

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

MLM

aka Zolo

Mja, COM resources "leaken" niet op de heap misschien, dat weet ik niet zeker.
Gebruik je een wrapper zoals CComPtr<T> ofzo om je COM resources te managen?

-niks-


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:51

.oisyn

Moderator Devschuur®

Demotivational Speaker

KillerZero86 schreef op zaterdag 01 december 2012 @ 18:18:
Het programma gebruikt in eerste instante rond de 180 MB geheugen en als je dan van kinect wisselt is het 220-230 MB. En daarna 270-280 MB, enz.
De hoeveelheid geheugen die task manager rapporteert is niet een valide indicatie van hoeveel de applicatie daadwerkelijk gebruikt. Het kan ook zijn dat de heap gewoon groter is gemaakt door een interne allocatie, terwijl die heap niet fysiek kleiner is geworden nadat die allocatie is vrijgegeven. Een volgende allocatie kan dan gewoon dat geheugen gebruiken.

That said, de CRT functies tracken de CRT heap. Kan best dat het Kinect gebeuren zijn eigen heap gebruikt, en die lekken zul je nooit tracken. Release() je wel alle COM objecten?

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.


Acties:
  • 0 Henk 'm!

  • KillerZero86
  • Registratie: Mei 2010
  • Laatst online: 12-07 23:09
Hoewel je heap verhaal het een en ander zou kunnen verklaren twijfel ik toch of het wel klopt. Als ik bijvoorbeeld geen enkele Release meer doe groeit de hoeveelheid gebruikte memory enorm, bijna 100 MB per kinect wissel. En ik Release() op dit moment alle pointers die in principe interfaces zijn. Ik zal nog eens uitgebreid nagaan welke objecten er een Release() methode hebben en eventueel meer objecten op die manier destructen.

@MLM: nee, geen wrappers om mn pointers, alleen naked pointers. Dit is een van mn eerste C++ projecten dus ik wou eerst goed aan de gang met de basis en leren waarom wrappers om pointers zo belangrijk zijn voor ze te gaan gebruiken.

Acties:
  • 0 Henk 'm!

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

MLM

aka Zolo

Het lijkt me dat je nu door hebt waarom wrappers om pointers belangrijk zijn :)

Bij het opsporen van deze bug bijvoorbeeld, is het ideaal om uit te kunnen sluiten dat je COM pointers direct leakt, omdat je een goeie wrapper hebt. Dan zijn de mogelijke leaks gereduceerd tot heap-objecten met een COM-pointer-wrapper erin (en die kun je vinden met een CRT heap tracker) :P

-niks-

Pagina: 1