Sfaturi programatorilor și pierderi de memorie Trix de captură

În „Task Manager“ este foarte comun pentru a vedea că unele programe ocupă destul de obscen cantitate de memorie. Acest lucru este în special caracteristică a browser-ului de Internet. Mai devreme sau mai târziu, se confruntă cu sarcina de a prinde pierderi de memorie înainte de fiecare dezvoltator. Astăzi vom învăța cum să facă acest lucru în C ++, pe MSVC.

Căutați pierderi de memorie, vom rula Windows și codul pentru ansamblul de a utiliza un compilator de la Microsoft. Există mai multe modalități de a evita fețele de memorie, dar regula de bază a acestei lupte poate fi definită ca „pentru a pune în aplicare tot ce au luat.“ Din păcate, „codificarea de luptă“ nu este întotdeauna posibil. factorul uman Banal sau excepție ar putea anula cu ușurință declanșată operatorul șterge. În acest articol nu vom discuta despre ce să facă și ce nu merită să memorie nu este scurgeri. Vom acționa în contextul problemelor existente: există o scurgere și a trebuit să-l blocheze.
Pentru a rezolva puzzle-uri, mulți programatori folosesc biblioteci terțe părți (și mai tare a scrie propriile lor de gestionare a memoriei), dar vom începe cu ceva mai simplu - de exemplu, prin intermediul utilizării Debug CRT.

Pentru a utiliza Debug CRT este necesar pentru a conecta Header corespunzătoare, și să permită utilizarea Debug Heap Alloc Harta. Acest lucru se face cu doar câteva linii de cod:

Conectarea CRT Debug

# ifdef _DEBUG
#include
_CRTDBG_MAP_ALLOC #define
# endif

După acești pași, alocarea de memorie de date noi și malloc () va fi înfășurat într-o _CrtMemBlockHeader structură specială. Cu acest înveliș putem găsi numele fișierului și linia pe care este rezervata liknutaya de memorie, volumul și datele în sine. Toate intrările sunt combinate într-o listă dublu legată, așa este ușor pentru a rula și de a găsi zonele cu probleme.

structura _CrtMemBlockHeader

typedef struct _CrtMemBlockHeader
struct _CrtMemBlockHeader * pBlockHeaderNext;
struct _CrtMemBlockHeader * pBlockHeaderPrev;
char * szFileName;
int nLine;
size_t nDataSize;
int nBlackUse;
lRequest lung;
gap unsigned char [nNoMansLandSize];
date unsigned char [nDataSize];
unsigned char anotherGap [nNoMansLandSize];

Pentru a trece prin această listă, trebuie să utilizați _CrtDumpMemoryLeaks funcția (). Este nevoie de nici un parametru și pur și simplu afișează o listă de blocuri de memorie scurgeri. Dar, din păcate, ea nu ne spune nimic despre fișierul și linia în care este alocată memorie. Rezultatul acestei funcții arată astfel:

_CrtDumpMemoryLeaks Concluzie ()

Detectate scurgeri de memorie!
Dumping obiecte ->
Bloc normal de la 0x00128788, 4 bytes.
date: <> 00 00 00 00
Bloc normal de la 0x00128748, 4 bytes.
date: <> 00 00 00 00
benă obiect complet.

Iată cum: în Microsoft Visual C ++ 6.0 a fost o redefinire de noi caracteristici în fișierul crtdbg.h, care a fost de a arăta cu exactitate fișierul și linia în care a avut loc alocarea. Dar nu a dat rezultatul dorit - DOSAR: LINE întotdeauna desfășurat în linia de fișier crtdbg.h 512. În următoarele versiuni ale Microsoft eliminat această funcție, la toate, și întreaga povară a responsabilității pune pe programatori. Asigurați-o ieșire normală, puteți utiliza următoarele suprareglările:

noi Supracomanda

#define nou nou (_NORMAL_BLOCK, __FILE__, __LINE__)

Această linie, este de dorit să se efectueze într-un fișier antet comune și conectați-l după crtdbg.h. Acum, sarcina noastră este să-l scrie în orice jurnal, sau cel puțin în consola de ieșire. Pentru a redirecționa de ieșire avem nevoie de două funcții: _CrtSetReportMode și _CrtSetReportFile. Al doilea parametru poate fi un mâner _CrtSetReportFile fișierul nostru jurnal sau de pavilion de ieșire la stdout.

ieșire Redirecționarea

_CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE);
// afișa toate stdout
_CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDOUT);

În această metodă există o problemă - afișează informații de memorie nu este scurgeri, dar pur și simplu nu au avut timp să se întoarcă. Acest lucru, de exemplu, poate fi orice variabilă globală sau obiect. Avem nevoie pentru a elimina cumva aceste bucăți de memorie din _CrtDumpMemoryLeaks de ieșire (). Acest lucru se face după cum urmează:

_CrtDumpMemoryLeaks acoperire Restriction ()

int _tmain (int argc, _TCHAR * argv [])
_ms _CrtMemState;
_CrtMemCheckpoint (_ms);
// unele logica merge aici.
_CrtMemDumpAllObjectsSince (_ms);
return 0;
>

Înregistrăm starea inițială a memoriei într-o structură specială utilizând funcția _CrtMemCheckpoint (), iar în cele din urmă, folosind _CrtMemDumpAllObjectsSince (), obținem tot ce a curs imediat după ce am făcut o distributie de spirit.

Acesta este modul în care, cu ajutorul unor funcții simple Debug CRT, putem lupta eficient cu chipuri de memorie în programul nostru. Desigur, acest lucru nu este un substitut pentru biblioteci serioase pentru prinderea scurgeri de informații, dar este destul de potrivit pentru proiecte mai mici.

Visual Detector de scurgeri

Visual Detector de scurgeri - aceasta este o bibliotecă terță parte, dar, de fapt, este un add-on Debug CRT, pe care am considerat un pic mai devreme. Utilizați este destul de simplu - trebuie doar să includă vld.h fișierul antet în orice fișier de proiect. Dar, cu două rezerve.

În primul rând, dacă facem proiectul are mai multe module binare (DLL sau EXE), apoi includ pentru vld.h ar trebui să se facă cel puțin un fișier sursă pentru fiecare modul. Asta este, dacă avem după compilarea de ieșire este module_1.dll și module_2.dll, atunci trebuie să facem #include cel puțin module_1.h și module_2.h.

În al doilea rând, includerea fișierului header vizual detector de scurgeri trebuie să aibă loc după Heather prekompiled. Aceasta este, după stdafx.h, și alte astfel de fișiere. După îndeplinirea acestor condiții este suficientă pentru a rula programul în depanare construiește, iar biblioteca va începe imediat să lucreze.

Visual Detector de scurgeri pot fi personalizate pentru nevoile dumneavoastra. Config stocate în fișierul vld.ini, care, la rândul său, este în directorul cu un VLD. Fișierul de configurare poate fi copiate în directorul proiectului, iar apoi biblioteca va folosi această copie cu setări individuale pentru fiecare proiect.
Setări pentru Visual Detector de scurgeri de tuning abundă. De exemplu, puteți configura aceeași ieșire într-un fișier sau în consola de studio de depanare. Ea devine ReportTo cheie. Setarea implicită este «debugger», dar puteți schimba valoarea la «fișier» sau «ambele». Sper să explice semnificația lor nu este necesară.

Dacă includem ieșirea într-un fișier, trebuie să specificați calea către acest fișier folosind parametrul ReportFile. Puteți selecta, de asemenea, codificarea fișier folosind ReportEncoding: ASCII sau Unicode.

Cu toate acestea, există o opțiune interesantă pentru a căuta fețele în biblioteca în sine (SelfTest). Da, se întâmplă uneori. Dacă încercați, puteți obține de ieșire ceva de genul:

EROARE: Visual Detector de scurgeri: detectat o scurgere de memorie internă la Visual Detector de scurgeri.

Un alt VLD vă permite să limitați dimensiunea ieșirii haldei la un jurnal, sau chiar suprima această concluzie, și ajusta adâncimea de penetrare a metodei stivei, și așa mai departe. Dar acesta este un lucru specific, care ar putea fi util pentru unii, și nu unele. Per total detector vizual este simplu, ușor de utilizat și nu necesită o mulțime de cod pentru a activa modul de căutare a scurgerilor.

Tot ceea ce am considerat mai sus, este important atât pentru Windows și MS Visual Studio. Dar există și alte sisteme de operare. Valgrind doar pentru ei. Acesta ruleaza pe Linux și Mac OS X și este folosit nu numai pentru a captura fețele de memorie, dar, de asemenea, pentru depanare de memorie și crearea de profiluri (de colectare are programul de lucru). De fapt, Valgrind este o mașină virtuală, utilizați metoda compilate JIT. Efortul ei nu se execută direct pe procesorul calculatorului, și este tradus în așa-numita „reprezentare intermediară“. În acest punct de vedere și este de lucru Valgrind. Mai precis, instrumentele de lucru, dar un pic mai târziu despre asta.

După procesarea reprezentarea intermediară Valgrind depășește orice înapoi în cod mașină. Aceste acțiuni în mod semnificativ (de 4-5 ori) încetini executarea programului. Dar este destul de o taxă rezonabilă pentru controlul consumului de memorie. Așa cum am spus mai sus, Valgrind oferă mai multe instrumente. Cele mai populare dintre ele - Memcheck. Acesta înlocuiește selecția standard a implementării limbajul C a propriei sale de memorie. Memcheck detectează încercări de utilizare a memoriei neinițializate, citire / scriere după eliberarea sa de la capăt și blocul selectat, și pierderi de memorie.

Există și alte instrumente, cum ar fi Addrcheck - mai ușor, dar versiune mai puțin funcțională Memcheck. instrumente Helgrind și DRD sunt folosite pentru a găsi erori în codul multifir. Cu alte cuvinte, Valgrind lucru mult mai puternic decât o bibliotecă pentru a găsi chipuri de memorie.

concluzie

pierderi de memorie - una dintre cele mai frecvente probleme în programare. Chiar și cel mai experimentat dintre noi poate face rost de o pereche de fețe. Instrumente pentru captarea marea lor varietate, iar aceste câteva pagini pentru a vă ajuta să lupte cu pierderi de memorie.

Arată acest articol unui prieten: