Gasirea variabilelor care produc memory leak-uri

Intrebari despre programarea cu VC++ incluzand mediul de dezvoltare, instalare, setari, debugger, compilator, linker si documentatie.
User avatar
black_atus
Membru
Membru
Posts: 139
Joined: 20 Jun 2012, 10:20
Judet: Prahova
Location: Ploiesti

Gasirea variabilelor care produc memory leak-uri

Post by black_atus » 09 Aug 2012, 16:37

Buna ziua,

Sunt incepator in programarea in VC++ si nu stiu care e cea mai simpla metoda pt depistarea si rezolvarea corecta in cazul memory leak-urilor.
Metoda care o folosesc acum implica modificarea codului pentru fiecare variabila care aloca spatiu folosind operatorul "new" ca in exemplul urmator:


testPointer = new dClass;

long allocReqNum = 1;
unsigned int dSize = sizeof(*testPointer);
_CrtIsMemoryBlock(testPointer, dSize , &allocReqNum, NULL, NULL);

Dupa care compar valoarea lui allocReqNum cu numerele de alocare a memoriei din Output unde apar memory leak-uri. Daca numerele coincid am gasit problema.

Pentru ca programul este destul de mare ar trebui sa fac asta in foarte multe locuri...peste tot unde am alocare dinamica ...

Am citit pe internet ca exista o metoda mai usoara folosind fereastea Watch din VC++. Am incercat dar nu am reusit. In plus am observat ca numerele de alocare a memoriei se modifica de la compilare la compilare.
Sper ca am explicat destul de bine si rog oricine stie o metoda mai buna sa-mi descrie pasii.

Multumesc.


Cu stima,
Daniel Constantin

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi

Re: Gasirea variabilelor care produc memory leak-uri

Post by Ovidiu Cucu » 09 Aug 2012, 17:49

black_atus wrote: Am citit pe internet ca exista o metoda mai usoara folosind fereastea Watch din VC++. Am incercat dar nu am reusit.
Ce-ai citit, ce-ai incercat si n-ai reusit?

User avatar
mihk
Junior
Junior
Posts: 39
Joined: 03 Jul 2009, 14:51

Re: Gasirea variabilelor care produc memory leak-uri

Post by mihk » 09 Aug 2012, 21:34

In Watch nu stiu, dar primesti in Output parca toate leak-urile.
Totusi de ce nu folosesti un smart pointer ?

Sintaxa nu difera foarte mult, si dupa ce te obisnuiesti cu ea (sintaxa/clasa), n-o sa mai vrei inapoi.
Exista boost::shared_ptr<T>
Sintaxa ar trebui sa fie:
boost::shared_ptr<dClass> testPointer = new dClass();
boost::shared_ptr<dClass> ptr2 = testPointer;
//pentru a acesa metode interne:
testPointer->Functie_dClass(...);
etc.

Daca boost e prea mult, ai putea incerca autoptr.hpp
Sintaxa ar fi ceva de genul:

Code: Select all

#include <iostream>
#include "autoptr.hpp"

class dClass
{
public:
	dClass(long value):m_value(value){}
	~dClass(){ std::cout << "\ndClass::~dClass() done" ; }

	long GetVal()const{return m_value;}
private:
	long m_value;
};


int main(int, char**)
{
	misc::autoptr<dClass> intptr = new dClass(200);
	if(intptr.IsNull())
		{ /*ptr invalid*/}
	else
		{
			std::cout << "\ndClass's value= " << intptr->GetVal() ;
		}
	std::cout << "\nend program";
	return 0;
}

Caut profesor.

Viorel
Microsoft MVP
Microsoft MVP
Posts: 285
Joined: 13 Jul 2007, 12:26

Re: Gasirea variabilelor care produc memory leak-uri

Post by Viorel » 09 Aug 2012, 22:55

Încearcă şi metoda descrisă aici: http://support.microsoft.com/kb/140858, la secţiunea Sample Code. Toate definiţiile pot fi făcute în fişierul „stdafx.h” (dacă îl foloseşti).

Sistemul va afişa fişierul şi linia în care s-a alocat memoria.

User avatar
bu7ch3r
Membru++
Membru++
Posts: 326
Joined: 17 May 2011, 15:17
Judet: Iaşi
Location: Sofia
Contact:

Re: Gasirea variabilelor care produc memory leak-uri

Post by bu7ch3r » 09 Aug 2012, 23:14

Cu asta ai incercat?
http://www.codeproject.com/Articles/981 ... k-Detectio
Apoi poti sa te joci si cu:
http://www.microsoft.com/en-us/download ... x?id=20028

Poi sa folosesti si
http://www.codeproject.com/Articles/313 ... ing-Windbg

Sa nu-l uitam pe: Intel Parallel Studio dar nici pe:
http://www.deleaker.com/ - daca ai GDI leaks - la 10,000 de GDI objects aplicatia crapa din cate imi amintesc :D(Yahoo Messenger crapa daca tot faceai resize la un moment dat in tema clasica de Windows)

Si....Static code check ? :-?? te mai ajuta din cand in cand mai ales daca esti incepator si nu vezi memory leak-uri evidente:)

Spor!
Cu stima,
Lupu Claudiu

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Gasirea variabilelor care produc memory leak-uri

Post by Silviu Ardelean » 10 Aug 2012, 08:14

mihk wrote:In Watch nu stiu, dar primesti in Output parca toate leak-urile.
Totusi de ce nu folosesti un smart pointer ?

Sintaxa nu difera foarte mult, si dupa ce te obisnuiesti cu ea (sintaxa/clasa), n-o sa mai vrei inapoi.
Exista boost::shared_ptr<T>
Sintaxa ar trebui sa fie:
boost::shared_ptr<dClass> testPointer = new dClass();
boost::shared_ptr<dClass> ptr2 = testPointer;
//pentru a acesa metode interne:
testPointer->Functie_dClass(...);
etc.
O mica observatie. shared_ptr folosit necorespunzator poate da destule batai de cap in momentul in care ai referinte circulare si reference counterul nu descreste la 0 la pierderea scopului. Pentru a evita astfel de situatii trebuie apelat la weak_ptr cand pointerul nu e "owner" pe obiectul pointat.
Dar si in cazul asta un tool ca Visual Leak Detector recomandat de Claudiu te poate scoate din incurcatura.

User avatar
black_atus
Membru
Membru
Posts: 139
Joined: 20 Jun 2012, 10:20
Judet: Prahova
Location: Ploiesti

Re: Gasirea variabilelor care produc memory leak-uri

Post by black_atus » 10 Aug 2012, 11:34

Buna ziua,

Multumesc pentru raspunsuri.

Solutia pe care am gasit-o pe internet(pare destul de simplu de utilizat deoarece din cate am inteles trebuie sa introduci in watch window {,,msvcrtd.dll}*__p__crtBreakAlloc() si la value numarul de alocare dinamica pe care il iau din output de la memory leak si ar trebui ca asta sa fie un fel de break point in debug, aunci cand se aloca spatiu si are numarul de alocare dinamica cel dat de mine in watch window ar trebui sa se opreasca acolo) si nu reusesc sa o folosesc.

UItati linkul gasit de mine:
http://support.microsoft.com/kb/151585

Nici nu pot folosi smart pointeri pentru ca nu stiu care pointeri nu sunt dealocati si incerc solutia care implica sa schimb cat mai putin cod.(Nici nu stiu inca sa folosesc smart pointeri :)) mai am foarte mult de invatat ... v-am spus sunt incepator ...)

Multumesc mult.
Cu stima,
Daniel Constantin

User avatar
black_atus
Membru
Membru
Posts: 139
Joined: 20 Jun 2012, 10:20
Judet: Prahova
Location: Ploiesti

Re: Gasirea variabilelor care produc memory leak-uri

Post by black_atus » 10 Aug 2012, 11:36

O sa incerc solutia cu Visual Leak Detector recomandata de Claudiu.
Cu stima,
Daniel Constantin

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi

Re: Gasirea variabilelor care produc memory leak-uri

Post by Ovidiu Cucu » 11 Aug 2012, 10:18

Ca sa detectezi memory leaks in Visual Studio, nu-ti trebuie neaparat cinestiece addon-uri sau scule bengoase.
Pentru asta, exista o serie intreaga de functii in CRT.
Cel mai simplu (fara prea multe fineturi), e sa apelezi _CrtDumpMemoryLeaks inainte de iesirea din program.

Daca rulezi programelul simplu de mai jos in mod DEBUG

Code: Select all

#include <crtdbg.h>

int main()
{
   char* p = new char[5]; 
   // ...
   _CrtDumpMemoryLeaks();
   return 0;
}
obtii in fereastra "Output"

Code: Select all

Detected memory leaks!
Dumping objects ->
{59} normal block at 0x004F4FA0, 5 bytes long.
 Data: <     > CD CD CD CD CD 
Object dump complete.
In momentul asta stim ca sunt memory leaks in program, nu si sursa lor.
Ca sa putem detecta si sursa, definim operatorul new, dupa cum urmeaza:

Code: Select all

#include <crtdbg.h>

#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif // _DEBUG

int main()
{
   char* p = new char[5];
   // ...
   _CrtDumpMemoryLeaks();
   return 0;
}
Acuma in output avem

Code: Select all

Detected memory leaks!
Dumping objects ->
c:\projects\console_test\console_test.cpp(12) : {59} normal block at 0x00804FA0, 5 bytes long.
 Data: <     > CD CD CD CD CD 
Object dump complete.
Au aparut niste informatii in plus care imi spun sursa (numele fisierului sursa si numarul de linie).
Mai mult, poti da dublu-click pe acea line din fereasta "Output" iar VS-ul te va duce in editor, exact la sursa.

Asta a fost pentru alocarile cu operatorul new. Daca vrei sa si gasesti leak-urile generate de functii CRT (malloc s.a.m.d.) trebuie sa definesti _CRTDBG_MAP_ALLOC.
Deci, un exemplu putin mai complet ar fi:

Code: Select all

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif // _DEBUG

int main()
{
   char* p1 = (char*)malloc(7);
   char* p2 = new char[5];
   // ...
   _CrtDumpMemoryLeaks();
   return 0;
}
In output am acum:

Code: Select all

Detected memory leaks!
Dumping objects ->
c:\projects\console_test\console_test.cpp(15) : {60} normal block at 0x00811308, 5 bytes long.
 Data: <     > CD CD CD CD CD 
c:\projects\console_test\console_test.cpp(14) : {59} normal block at 0x00814FA0, 7 bytes long.
 Data: <     > CD CD CD CD CD CD CD
Object dump complete.
Simplu!
Nota: Daca folosesti MFC e si mai simplu. Vezi aici: viewtopic.php?f=30&t=1769

[ Later edit ]
De curiozitate, m-am uitat prin acel Visual Leak Detector.
E Ok pentru cine prefera scule gata facute (cu tot alaiul lor de probleme) in loc sa puna cu mana lui in program 4-5 linii de cod.
Ah, mai are si ceva ficeruri, cum ar fi dump la call stack si dump complet la data, ceea ce pentru scopul nostru simplu de a detecta codul sursa care genereaza memory leaks, nu-s macar "nice to have" (sau altfel zis, sunt "frectie la picior de lemn").
Acuma tu alegi...
Eu zic, ceea ce ti-am sugerat eu e mai simplu.

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Gasirea variabilelor care produc memory leak-uri

Post by Silviu Ardelean » 11 Aug 2012, 13:23

Odata ce ai instalat VLD-ul pe masina de lucru, incluzi .lib-ul, doua .h-uri in proiect si sa faci un #include "vld.h" intr-un fisier .cpp central (ex. fisierul clasei *App). Si nu te mai doare capul sa incluzi in alte parti linii de cod.

Spre deosebire de aceasta solutia data, cu VLD obtii si callstack-uri pentru zonele de memorie ce genereaza leak-uri. Iar acest aspect e foarte util in proiectele adevarate.

neagu_laurentiu
Membru++
Membru++
Posts: 919
Joined: 23 Jul 2007, 11:32

Re: Gasirea variabilelor care produc memory leak-uri

Post by neagu_laurentiu » 11 Aug 2012, 13:40

Voi chiar uitati pe unde ati alocat ori sa faceti "curatenie" la locul de munca ?

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Gasirea variabilelor care produc memory leak-uri

Post by Silviu Ardelean » 11 Aug 2012, 13:50

neagu_laurentiu wrote:Voi chiar uitati pe unde ati alocat ori sa faceti "curatenie" la locul de munca ?
E o discutie pe tehnici de detectare a leak-urilor. Sa nu mai participam la ea pentru ca stim sa facem "curatenie"?

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi

Re: Gasirea variabilelor care produc memory leak-uri

Post by Ovidiu Cucu » 11 Aug 2012, 14:11

Silviu Ardelean wrote:Odata ce ai instalat VLD-ul pe masina de lucru, incluzi .lib-ul, doua .h-uri in proiect si sa faci un #include "vld.h" intr-un fisier .cpp central (ex. fisierul clasei *App). Si nu te mai doare capul sa incluzi in alte parti linii de cod.
Da Silviu, mersi, nu stiam sa includ un header si sa ma leg la un lib... ;)
Ce sustii tu e *NIX-style programming (aka mura-n gura, aka para malaiata) adica: google search, download si... fleoshck balegutza in proiect. :)
O mizerie de ici, o mizerie de colo, pana nu mai stii nici in cer nici in pamant ce-i prin proiect (chiar acum ma distrez cu un proiect de genul asta).
Prefer sa ma doara capu pentru liniile pe care le includ eu, decat pentru ale altora.
Daca zici ca e mai simplu (+ more reliable and maintainable) sa introduci ditamai modulul cules de-aiurea, in locul a cateva linii de cod, traba ta.
Cum am mai zis, "tu alegi".
Silviu Ardelean wrote:Spre deosebire de aceasta solutia data, cu VLD obtii si callstack-uri pentru zonele de memorie ce genereaza leak-uri. Iar acest aspect e foarte util in proiectele adevarate.
Sure, ca sa gasim sursa de memory leaks in "proiectele adevarate", e nevoie si de "frectii la picior de lemn" (pardon "la picior de stiva").
Iar daca vrei neaparat frectie, nu poti sa pui un amarat de breakpoint si sa tragi un ochi in "Call Stack", nuuuu... iti trebuie scula "profesionala". :D
Iarasi, tu alegi.
neagu_laurentiu wrote:Voi chiar uitati pe unde ati alocat ori sa faceti "curatenie" la locul de munca ?
Iaca multi nu stiu sau uita, asa ca uneori e nevoie si de astea.

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Gasirea variabilelor care produc memory leak-uri

Post by Silviu Ardelean » 11 Aug 2012, 15:09

Ovidiu Cucu wrote:
Silviu Ardelean wrote:Odata ce ai instalat VLD-ul pe masina de lucru, incluzi .lib-ul, doua .h-uri in proiect si sa faci un #include "vld.h" intr-un fisier .cpp central (ex. fisierul clasei *App). Si nu te mai doare capul sa incluzi in alte parti linii de cod.
Da Silviu, mersi, nu stiam sa includ un header si sa ma leg la un lib... ;)
Nu m-am adresat in mod personal... ci vorbeam dpdv al pasilor de urmat. Tu alegi, daca o iei ca o lectie desi nu asta a fost intentia mea.
Ovidiu Cucu wrote:Ce sustii tu e *NIX-style programming (aka mura-n gura, aka para malaiata) adica: google search, download si... fleoshck balegutza in proiect. :)
O mizerie de ici, o mizerie de colo, pana nu mai stii nici in cer nici in pamant ce-i prin proiect (chiar acum ma distrez cu un proiect de genul asta).
Prefer sa ma doara capu pentru liniile pe care le includ eu, decat pentru ale altora.
Mai *NIX style programming e sa te apuci sa impodobesti pomul, pardon, codul cu tot felul de lucruri ce ai nevoie doar la un moment dat (a la mockito style). Stii ca prin lumea *NIX logging debugging style e la rang de arta in anumite situatii (cam la fel si cu impodobirea...).
Cu un ifdef scap si de eventuale probleme cand n-am nevoie de el sau nu vreau sa instalez VLD-ul pe alta masina (unde de altfel, as putea obtine un crash inainte de startul aplicatiei daca n-am VLD-ul instalat).

Code: Select all

#ifdef _LEAKS
#include "vld.h"
#endif
Tu alegi cate de multe globuri vrei sa pui in pod. :) Eu aleg, unul si bun cules din proiectului CodePlex de la MS.
Ovidiu Cucu wrote:
Silviu Ardelean wrote:Spre deosebire de aceasta solutia data, cu VLD obtii si callstack-uri pentru zonele de memorie ce genereaza leak-uri. Iar acest aspect e foarte util in proiectele adevarate.
Sure, ca sa gasim sursa de memory leaks in "proiectele adevarate", e nevoie si de "frectii la picior de lemn" (pardon "la picior de stiva").
Iar daca vrei neaparat frectie, nu poti sa pui un amarat de breakpoint si sa tragi un ochi in "Call Stack", nuuuu... iti trebuie scula "profesionala". :D
Iarasi, tu alegi.
Daca de exemplu ai de-a face cu un proiect mai mare editat de mai multe persoane cand esti nevoit sa elimini leakuri rezultate de referinte circulare facute prin folosirea "abuziva" de shared_ptr-i, e alegerea ta daca vrei sa faci debuging step by step. :ugeek:

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi

Re: Gasirea variabilelor care produc memory leak-uri

Post by Ovidiu Cucu » 11 Aug 2012, 15:29

Of, de unde am plecat si unde am ajuns! Mai lipseste sa dam un tur prin boost, C++11 si in cele din urma sa-i tragem un articol trasnet "shared_ptr - pros and pitfalls" ca sa avem pe ce ne certa in continuare. :)

Am dat o solutie, zic eu simpla la intrebarea din OP.
Cine vrea s-o aplice, bine. Cine nu, noroc bun! Nu ne mai invartim in jurul cozii.

[ Later edit, off-topic ]
Silviu, daca aveti asa mari probleme cu shared_ptr, nu-l mai folositi. Sau il folositi insa nu "abuziv". E simplu. ;)
Cat despre referinte circulare, daca inteleg eu bine la ce te referi, cred c-ar trebui sa-l dati putin cu capu de pereti pe domnul Architect. :biggrin:

Post Reply