Hoe u geheugenlek in een C++ -code / project kunt vinden?

Ik ben een C++ -programmeur op het Windows-platform. Ik gebruik Visual Studio 2008.

Ik eindig meestal in de code met geheugenlekken.

Normaal vind ik het geheugenlek door de code te inspecteren, maar het is omslachtig en is niet altijd een goede aanpak.

Aangezien ik een betaalde geheugenlekdetectietool niet kan betalen, wilde ik dat jullie de best mogelijke manieren suggereren om geheugenlekken te vermijden.

  1. Ik wil de weten hoe de programmeur geheugenlekken kan vinden.
  2. Is er een standaard of procedure die men moet volgen om ervoor te zorgen dat er geen geheugenlek in het programma is?

Antwoord 1, Autoriteit 100%

Instructies

Dingen die u nodig heeft

  • vaardigheid in C++
  • C++ Compiler
  • debugger en andere onderzoekende softwaretools

1

Begrijp de basisprincipes van de operator. De operator C++ newWEERGEBBEN HEEP-geheugen. De deleteOperator bevrijdt heapgeheugen. Voor elke new, moet u een deletezodat u hetzelfde geheugen bevrijdt dat u hebt toegewezen:

char* str = new char [30]; // Allocate 30 bytes to house a string.
delete [] str; // Clear those 30 bytes and make str point nowhere.

2

ALLEEN geheugen Reallocate als u hebt verwijderd. In de onderstaande code verwerft streen nieuw adres met de tweede toewijzing. Het eerste adres is onherstelbaar verloren, en dat geldt ook voor de 30 bytes waarnaar hij wees. Nu zijn ze onmogelijk om te bevrijden, en je hebt een geheugenlek:

char* str = new char [30]; // Give str a memory address.
// delete [] str; // Remove the first comment marking in this line to correct.
str = new char [60]; /* Give str another memory address with
                                                    the first one gone forever.*/
delete [] str; // This deletes the 60 bytes, not just the first 30.

3

Let op die aanwijzertoewijzingen. Elke dynamische variabele (toegewezen geheugen op de heap) moet worden geassocieerd met een aanwijzer. Wanneer een dynamische variabele wordt losgekoppeld van zijn aanwijzer(s), wordt het onmogelijk om te wissen. Nogmaals, dit resulteert in een geheugenlek:

char* str1 = new char [30];
char* str2 = new char [40];
strcpy(str1, "Memory leak");
str2 = str1; // Bad! Now the 40 bytes are impossible to free.
delete [] str2; // This deletes the 30 bytes.
delete [] str1; // Possible access violation. What a disaster!

4

Wees voorzichtig met lokale verwijzingen. Een pointer die u in een functie declareert, wordt op de stapel toegewezen, maar de dynamische variabele waarnaar deze verwijst, wordt op de heap toegewezen. Als u het niet verwijdert, blijft het bestaan nadat het programma de functie verlaat:

void Leak(int x){
char* p = new char [x];
// delete [] p; // Remove the first comment marking to correct.
}

5

Let op de vierkante accolades na ‘verwijderen’. Gebruik alleen deleteom een enkel object vrij te maken. Gebruik delete []met vierkante haken om een heap-array vrij te maken. Doe zoiets niet:

char* one = new char;
delete [] one; // Wrong
char* many = new char [30];
delete many; // Wrong!

6

Als het lek al is toegestaan, zoek ik het meestal met deleaker (kijk hier: http://deleaker.com).


Antwoord 2, autoriteit 11%

Je kunt een aantal technieken in je code gebruiken om een geheugenlek te detecteren. De meest gebruikelijke en gemakkelijkste manier om te detecteren is, definieer een macro, zeg DEBUG_NEW en gebruik deze, samen met vooraf gedefinieerde macro’s zoals __FILE__en __LINE__om het geheugenlek in uw code. Deze vooraf gedefinieerde macro’s vertellen u het bestands- en regelnummer van geheugenlekken.

DEBUG_NEW is slechts een MACRO die gewoonlijk wordt gedefinieerd als:

#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

Zodat overal waar u newgebruikt, het ook het bestand en het regelnummer kan bijhouden dat kan worden gebruikt om geheugenlek in uw programma te lokaliseren.

En __FILE__, __LINE__zijn vooraf gedefinieerde macro’sdie resulteren in respectievelijk de bestandsnaam en het regelnummer waar u ze gebruikt!

Lees het volgende artikel waarin de techniek van het gebruik van DEBUG_NEW met andere interessante macro’s heel mooi wordt uitgelegd:

Een platformonafhankelijke geheugenlekdetector


Van Wikpedia,

Debug_new verwijst naar een techniek in C++
operator te overbelasten en/of opnieuw te definiëren
new en operator delete om
onderschep de geheugentoewijzing en
deallocation-oproepen, en dus debuggen a
programma voor geheugengebruik. Het is vaak
omvat het definiëren van een macro met de naam
DEBUG_NEW, en maakt nieuw worden
zoiets als nieuw(_BESTAND_, _LINE_)
om de bestands-/regelinformatie op te nemen:
toewijzing.
Microsoft Visual C++ gebruikt
deze techniek in zijn Microsoft
Stichting lessen. Er zijn een paar
manieren om deze methode uit te breiden om te vermijden
macro-herdefinitie gebruiken terwijl u stilstaat
in staat om het bestand/de regel weer te geven
informatie op sommige platforms. Daar
zijn hier veel inherente beperkingen aan?
methode. Het is alleen van toepassing op C++, en
kan geheugenlekken niet opvangen door C
functies zoals malloc. Het kan echter
heel eenvoudig te gebruiken en ook erg
snel, in vergelijking met wat meer
complete oplossingen voor geheugenfoutopsporing.


Antwoord 3, autoriteit 5%

Het uitvoeren van “Valgrind” kan:

1) Help bij het identificeren van geheugenlekken– laat zien hoeveel geheugenlekken u heeft en wijs de regels in de code aan waar het gelekte geheugen is toegewezen.

2) Wijs op verkeerde pogingen om geheugen vrij te maken(bijv. ongepaste aanroep van delete)

Instructies voor het gebruik van “Valgrind”

1) Download valgrind hier.

2) Stel uw code samen met de vlag -g

3) In je shell-run:

valgrind --leak-check=yes myprog arg1 arg2

Waarbij “myprog” uw gecompileerde programma is en arg1, arg2de argumenten van uw programma.

4) Het resultaat is een lijst met oproepen naar malloc/newdie geen daaropvolgende oproepen hebben om gratis te verwijderen.

Bijvoorbeeld:

==4230==    at 0x1B977DD0: malloc (vg_replace_malloc.c:136)
==4230==    by 0x804990F: main (example.c:6)

Vertelt in welke regel de malloc(die niet was vrijgegeven) werd aangeroepen.

Zoals door anderen is opgemerkt, moet u ervoor zorgen dat u voor elke new/malloc-aanroep een volgende delete/freeoproep.


Antwoord 4, autoriteit 5%

Er zijn enkele bekende programmeertechnieken die u zullen helpen het risico op geheugenlekken uit de eerste hand te minimaliseren:

  • als u uw eigen dynamische geheugentoewijzing moet doen, schrijft u newen deletealtijd paarsgewijs, en zorgt u ervoor dat de toewijzings-/deallocatiecode paarsgewijs wordt aangeroepen
  • vermijd indien mogelijk dynamische geheugentoewijzing. Gebruik bijvoorbeeld vector<T> twaar mogelijk in plaats van T* t = new T[size]
  • gebruik “slimme aanwijzers” zoals slimme slimme aanwijzers (http: //www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm)
  • mijn persoonlijke favoriet: zorg ervoor dat je het concept van eigendom van een aanwijzer hebt begrepen en zorg ervoor dat je overal waar je aanwijzers gebruikt, weet welke code-entiteit de eigenaar is
  • leer welke constructors / toewijzingsoperators automatisch worden gemaakt door de C++-compiler, en wat dat betekent als je een klasse hebt die eigenaar is van een aanwijzer (of wat dat betekent als je een klasse hebt die een aanwijzer naar een object bevat nieteigen).

Antwoord 5, autoriteit 3%

Valgrind
http://valgrind.org/

en

GDB
http://www.gnu.org/software/gdb/


Antwoord 6, autoriteit 3%

Een onderzoek naar automatische geheugenlekcheckers

In dit antwoord vergelijk ik verschillende geheugenlek-checkers in een eenvoudig, gemakkelijk te begrijpen voorbeeld van geheugenlek.

Bekijk voor alles deze enorme tabel in de ASan-wiki waarin alle tools die de mens kent worden vergeleken: https://github.com/google/sanitizers/wiki/AddressSanitizerComparisonOfMemoryTools/d06210f759fec97066888e5f27c7e722832b0924

Het geanalyseerde voorbeeld is:

main.c

#include <stdlib.h>
void * my_malloc(size_t n) {
    return malloc(n);
}
void leaky(size_t n, int do_leak) {
    void *p = my_malloc(n);
    if (!do_leak) {
        free(p);
    }
}
int main(void) {
    leaky(0x10, 0);
    leaky(0x10, 1);
    leaky(0x100, 0);
    leaky(0x100, 1);
    leaky(0x1000, 0);
    leaky(0x1000, 1);
}

GitHub stroomopwaarts.

We zullen proberen te zien hoe duidelijk de verschillende tools ons wijzen op de lekkende oproepen.

tcmalloc van gperftools door Google

https://github.com/gperftools/gperftools

Gebruik op Ubuntu 19.04:

sudo apt-get install google-perftools
gcc -ggdb3 -o main.out main.c -ltcmalloc
PPROF_PATH=/usr/bin/google-pprof \
  HEAPCHECK=normal \
  HEAPPROFILE=ble \
  ./main.out \
;
google-pprof main.out ble.0001.heap --text

De uitvoer van de programma-uitvoering bevat de geheugenlekanalyse:

WARNING: Perftools heap leak checker is active -- Performance may suffer
Starting tracking the heap
Dumping heap profile to ble.0001.heap (Exiting, 4 kB in use)
Have memory regions w/o callers: might report false leaks
Leak check _main_ detected leaks of 272 bytes in 2 objects
The 2 largest leaks:
Using local file ./main.out.
Leak of 256 bytes in 1 objects allocated from:
        @ 555bf6e5815d my_malloc
        @ 555bf6e5817a leaky
        @ 555bf6e581d3 main
        @ 7f71e88c9b6b __libc_start_main
        @ 555bf6e5808a _start
Leak of 16 bytes in 1 objects allocated from:
        @ 555bf6e5815d my_malloc
        @ 555bf6e5817a leaky
        @ 555bf6e581b5 main
        @ 7f71e88c9b6b __libc_start_main
        @ 555bf6e5808a _start
If the preceding stack traces are not enough to find the leaks, try running THIS shell command:
pprof ./main.out "/tmp/main.out.24744._main_-end.heap" --inuse_objects --lines --heapcheck  --edgefraction=1e-10 --nodefraction=1e-10 --gv
If you are still puzzled about why the leaks are there, try rerunning this program with HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with HEAP_CHECK_MAX_POINTER_OFFSET=-1
If the leak report occurs in a small fraction of runs, try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB or with TCMALLOC_RECLAIM_MEMORY=false, it might help find leaks more re
Exiting with error code (instead of crashing) because of whole-program memory leaks

en de uitvoer van google-pprofbevat de heap-gebruiksanalyse:

Using local file main.out.
Using local file ble.0001.heap.
Total: 0.0 MB
     0.0 100.0% 100.0%      0.0 100.0% my_malloc
     0.0   0.0% 100.0%      0.0 100.0% __libc_start_main
     0.0   0.0% 100.0%      0.0 100.0% _start
     0.0   0.0% 100.0%      0.0 100.0% leaky
     0.0   0.0% 100.0%      0.0 100.0% main

De uitvoer wijst ons op twee van de drie lekken:

Leak of 256 bytes in 1 objects allocated from:
        @ 555bf6e5815d my_malloc
        @ 555bf6e5817a leaky
        @ 555bf6e581d3 main
        @ 7f71e88c9b6b __libc_start_main
        @ 555bf6e5808a _start
Leak of 16 bytes in 1 objects allocated from:
        @ 555bf6e5815d my_malloc
        @ 555bf6e5817a leaky
        @ 555bf6e581b5 main
        @ 7f71e88c9b6b __libc_start_main
        @ 555bf6e5808a _start

Ik weet niet zeker waarom de derde niet verscheen

In elk geval, wanneer meestal wanneer iets lekt, gebeurt het veel keren, en toen ik het op een echt project gebruikte, werd ik zo eenvoudig opgesproken op de lekkende functie.

Zoals vermeld op de uitvoer zelf, maakt dit een aanzienlijke uitvoering van de uitvoering op.

Verdere documentatie bij:

Zie ook: Hoe te gebruiken Tcmalloc?

Getest in ubuntu 19.04, Google-Perftools 2.5-2.

Adres Sanitizer (ASAN) Ook door Google

https://github.com/google/sanitizers

Eerder vermeld op: Hoe te vinden Memory Lek in een C++ -code / project? Todo vs Tcmalloc.

Dit is al geïntegreerd in GCC, dus u kunt het gewoon doen:

gcc -fsanitize=address -ggdb3 -o main.out main.c
./main.out 

en uitvoeringuitgangen:

=================================================================
==27223==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 4096 byte(s) in 1 object(s) allocated from:
    #0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
    #1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
    #2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
    #3 0x55bf86c5f210 in main /home/ciro/test/main.c:20
    #4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)
Direct leak of 256 byte(s) in 1 object(s) allocated from:
    #0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
    #1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
    #2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
    #3 0x55bf86c5f1f2 in main /home/ciro/test/main.c:18
    #4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)
Direct leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
    #1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
    #2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
    #3 0x55bf86c5f1d4 in main /home/ciro/test/main.c:16
    #4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)
SUMMARY: AddressSanitizer: 4368 byte(s) leaked in 3 allocation(s).

die duidelijk alle lekken identificeert. Leuk!

ASan kan ook andere coole controles uitvoeren, zoals out-of-bounds schrijft: Stack smashing gedetecteerd

Getest in Ubuntu 19.04, GCC 8.3.0.

Valgrind

http://www.valgrind.org/

Eerder genoemd op: https://stackoverflow.com/a/37661630/895245

Gebruik:

sudo apt-get install valgrind
gcc -ggdb3 -o main.out main.c
valgrind --leak-check=yes ./main.out

Uitvoer:

==32178== Memcheck, a memory error detector
==32178== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==32178== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==32178== Command: ./main.out
==32178== 
==32178== 
==32178== HEAP SUMMARY:
==32178==     in use at exit: 4,368 bytes in 3 blocks
==32178==   total heap usage: 6 allocs, 3 frees, 8,736 bytes allocated
==32178== 
==32178== 16 bytes in 1 blocks are definitely lost in loss record 1 of 3
==32178==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178==    by 0x10915C: my_malloc (main.c:4)
==32178==    by 0x109179: leaky (main.c:8)
==32178==    by 0x1091B4: main (main.c:16)
==32178== 
==32178== 256 bytes in 1 blocks are definitely lost in loss record 2 of 3
==32178==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178==    by 0x10915C: my_malloc (main.c:4)
==32178==    by 0x109179: leaky (main.c:8)
==32178==    by 0x1091D2: main (main.c:18)
==32178== 
==32178== 4,096 bytes in 1 blocks are definitely lost in loss record 3 of 3
==32178==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178==    by 0x10915C: my_malloc (main.c:4)
==32178==    by 0x109179: leaky (main.c:8)
==32178==    by 0x1091F0: main (main.c:20)
==32178== 
==32178== LEAK SUMMARY:
==32178==    definitely lost: 4,368 bytes in 3 blocks
==32178==    indirectly lost: 0 bytes in 0 blocks
==32178==      possibly lost: 0 bytes in 0 blocks
==32178==    still reachable: 0 bytes in 0 blocks
==32178==         suppressed: 0 bytes in 0 blocks
==32178== 
==32178== For counts of detected and suppressed errors, rerun with: -v
==32178== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

Nogmaals, alle lekken werden gedetecteerd.

Zie ook: Hoe gebruik ik Valgrind om geheugen te vinden lekken?

Getest in Ubuntu 19.04, Valgrind 3.14.0.


Antwoord 7, Autoriteit 3%

  1. Download debugging tools voor Windows .
  2. Gebruik de gflagsUTILITEIT om gebruikers-modus stapelsporen in te schakelen.
  3. Gebruik UMDHom meerdere snapshots van het geheugen van uw programma te nemen. Neem een ​​momentopname voordat het geheugen wordt toegewezen en neem een ​​tweede momentopname na een punt waarop u van mening bent dat uw programma het geheugen heeft gelekt. Misschien wilt u pauzes of aanwijzingen toevoegen in uw programma om u een kans te geven om UMDHuit te voeren en de snapshots te nemen.
  4. Voer UMDHopnieuw uit, dit keer in de modus die een verschil maakt tussen de twee snapshots. Het genereert dan een rapport met de oproepstacks van vermoedelijke geheugenlekken.
  5. Herstel je vorige gflags-instellingen als je klaar bent.

UMDHgeeft u meer informatie dan de CRT-foutopsporingsheap omdat het geheugentoewijzingen over uw hele proces in de gaten houdt; het kan u zelfs vertellen of componenten van derden lekken.


Antwoord 8, autoriteit 2%

Als je gcc gebruikt, is er gprof beschikbaar.

Ik wilde weten hoe de programmeur een geheugenlek vindt

Sommigen gebruiken tools, andere doen wat je doet, ook via peer-code review

Is er een standaard of procedure die men moet volgen om er zeker van te zijn dat er geen geheugenlek in het programma zit

Voor mij: wanneer ik dynamisch toegewezen objecten maak, plaats ik altijd de vrijmakende code erna en vul ik de code ertussen. Dit zou goed zijn als je zeker weet dat er geen uitzonderingen in de code tussen zitten. Anders maak ik gebruik van try-finally (ik gebruik C++ niet vaak).


Antwoord 9, autoriteit 2%

  1. In Visual Studio is een ingebouwde detector voor geheugenlek, genaamd C Runtime Library. Wanneer uw programma wordt afgesloten nadat de hoofdfunctie is teruggekeerd, zal CRT de debug-heap van uw toepassing controleren. als je nog blokken hebt toegewezen aan de debugheap, dan heb je een geheugenlek..

  2. Dit forum bespreekt een paar manieren om geheugenlekken in C/C++ te voorkomen..


Antwoord 10, autoriteit 2%

U kunt de tool Valgrind gebruiken om geheugenlekken te detecteren.

Om het lek in een bepaalde functie te vinden, gebruikt u ook exit(0) aan het einde van de functie en voert u deze vervolgens uit met Valgrind

`$` valgrind ./your_CPP_program 

Antwoord 11, autoriteit 2%

Zoek in uw code naar exemplaren van newen zorg ervoor dat ze allemaal voorkomen binnen een constructor met een overeenkomende verwijdering in een destructor. Zorg ervoor dat dit de enige mogelijke werpbewerking in die constructor is. Een eenvoudige manier om dit te doen is door alle aanwijzers in std::auto_ptrof boost::scoped_ptrte plaatsen (afhankelijk van of je wel of niet verplaatsingssemantiek nodig hebt). Zorg er voor alle toekomstige code voor dat elke bron eigendom is van een object dat de bron opruimt in zijn destructor. Als je move-semantiek nodig hebt, kun je upgraden naar een compiler die r-waardereferenties ondersteunt (volgens VS2010) en move-constructors maken. Als je dat niet wilt, kun je een verscheidenheid aan lastige technieken gebruiken waarbij je op gewetensvolle wijze swap gebruikt, of de Boost.Move-bibliotheek proberen.


Antwoord 12

Visual Leak Detector (VLD)is een gratis, robuust, open-source geheugenlekdetectiesysteem voor visuele C++.

Als u uw programma uitvoert onder de debugger van Visual Studio, zal Visual Leak Detector aan het einde van uw foutopsporingssessie een geheugenlekrapport uitvoeren. Het lekrapport bevat de volledige oproepstackdie laat zien hoe eventuele gelekte geheugenblokken zijn toegewezen. Dubbelklik op een regel in de oproepstack om naar dat bestand en de regel in het editorvenster te springen.

Als je alleen crashdumps hebt, kun je het Windbg !heap -lcommando gebruiken, het zal gelekte heapblokken detecteren. Open beter de optie gflags: “Maak gebruikersmodus-stacktrace-database”, dan ziet u de geheugentoewijzingsaanroepstack.


Antwoord 13

MTuneris een gratis multi-platform geheugenprofilerings-, lekdetectie- en analysetool die MSVC-, GCC- en Clang-compilers ondersteunt. Functies omvatten:

  • op tijdlijn gebaseerde geschiedenis van geheugengebruik en live geheugenblokken
  • krachtige filtering van geheugenbewerkingen op basis van heap, geheugentag, tijdbereik, enz.
  • SDK voor handmatige instrumentatie met volledige broncode
  • ondersteuning voor continue integratie via opdrachtregelgebruik
  • aanroep stack tree en tree map navigatie
  • veel meer.

Gebruikers kunnen elk softwaretargetingplatform profileren met GCC of Clang cross
samenstellers. MTuner wordt geleverd met ingebouwde ondersteuning voor Windows-, PlayStation 4- en PlayStation 3-platforms.


Antwoord 14

Op Windows kun je CRT-foutopsporingsheapgebruiken.

Is er een standaard of procedure die men moet volgen om er zeker van te zijn dat er geen geheugenlek in het programma zit.

Ja, gebruik geen handmatig geheugenbeheer (als je ooit handmatig deleteof delete[]aanroept, dan doe je het verkeerd). Gebruik RAII en slimme aanwijzers, beperk heaptoewijzingen tot het absolute minimum (meestal zijn automatische variabelen voldoende).


Antwoord 15

Als antwoord op het tweede deel van uw vraag,

Is er een standaard of procedure die men moet volgen om er zeker van te zijn dat er geen geheugenlek in het programma zit.

Ja, dat is er. En dit is een van de belangrijkste verschillen tussen C en C++.

In C++ mag je nooit newof deleteaanroepen in je gebruikerscode. RAIIis een veelgebruikte techniek, die het probleem van resourcebeheer vrijwel oplost. Elke bron in je programma (een bron is alles dat moet worden verworven en later moet worden vrijgegeven: bestandshandvatten, netwerksockets, databaseverbindingen, maar ook gewone geheugentoewijzingen en in sommige gevallen paren API-aanroepen (BeginX( )/EndX(), LockY(), UnlockY()), moeten worden verpakt in een klasse, waarbij:

  • de constructor verkrijgtde resource (door newaan te roepen als de resource een geheugentoewijzing is)
  • de vernietiger laatde bron vrij,
  • Het kopiëren en toewijzen wordt ofwel voorkomen (door de kopieerconstructor en de toewijzingsoperatoren privé te maken), of worden geïmplementeerd om correct te werken (bijvoorbeeld door de onderliggende bron te klonen)

Deze klasse wordt dan lokaal geïnstantieerd, op de stapel, of als een klasselid, en nietdoor newaan te roepen en een pointer op te slaan.

Je hoeft deze klassen vaak niet zelf te definiëren. De standaard bibliotheekcontainers gedragen zich ook op deze manier, zodat elk object dat is opgeslagen in een std::vectorwordt vrijgegeven wanneer de vector wordt vernietigd. Dus nogmaals, sla geen pointer op in de container (waarvoor jijnewen deletemoet aanroepen), maar eerder het object zelf(waardoor u gratisgeheugenbeheer krijgt). Evenzo kunnen slimme aanwijzerklassen worden gebruikt om objecten die alleen moeten worden toegewezen met neweenvoudig in te pakken en hun levensduur te regelen.

Dit betekent dat wanneer het object buiten bereik raakt, het automatisch wordt vernietigd en dat de bron wordt vrijgegeven en opgeruimd.

Als je dit consequent in je hele code doet, heb je gewoon geen geheugenlekken. Alles dat kongelekt wordt, is gekoppeld aan een destructor die gegarandeerd wordt aangeroepen wanneer de controle het bereik verlaat waarin het object is gedeclareerd.


Antwoord 16

AddressSanitizer(ASan) is een snelle geheugenfoutdetector.
Het vindt use-after-free en {heap,stack,global}-bufferoverloop-bugs in C/C++-programma’s. Het vindt:

  • Gebruik na gratis (dereferentie bungelende aanwijzer)
  • Heapbufferoverloop
  • Overloop stapelbuffer
  • Globale bufferoverloop
  • Gebruik na terugkomst
  • Fouten bij initialisatievolgorde

Deze tool is erg snel. De gemiddelde vertraging van het geïnstrumenteerde programma is ~2x.


Antwoord 17

Naast de tools en methodes die in de andere antwoorden worden gegeven, kunnen statische code-analysetools worden gebruikt om geheugenlekken (en ook andere problemen) op te sporen.
Een gratis en robuuste tool is Cppcheck. Maar er zijn nog veel meer tools beschikbaar. Wikipediaheeft een lijst met statische code-analysetools.


Antwoord 18

Zorg ervoor dat al het heapgeheugen met succes is vrijgemaakt. Het is niet nodig als u nooit geheugen op de heap toewijst. Als je dat doet, tel dan het aantal keren dat je malloc-geheugen hebt en tel het aantal keren op dat je geheugen vrijmaakt.


Antwoord 19

Noch “NIEUWE” of “DELETE” moet ooit worden gebruikt in de applicatecode. Maak in plaats daarvan een nieuw type dat het IDIOM Manager / Werknemer gebruikt, waarin de managerklasse toewijst en het geheugen bevrijdt en alle andere bewerkingen naar het arbeidsobject doorstuurt.

Helaas is dit meer werk dan het zou moeten zijn omdat C++ geen overbelasting van ‘operator’ heeft.. Het is nog meer werk in de aanwezigheid van polymorfisme.

Maar dit is de moeite waard omdat u zich nooit zult zorgen maken over geheugenlekken, wat betekent dat u niet eens hoeft te zoeken.

Other episodes