Sobes.tech
Middle
202

Hoe kan een geheugenlek optreden bij het gebruik van unique_ptr in C++?

Antwoord van AI

sobes.tech AI

Memorylek bij het gebruik van std::unique_ptr kan optreden in de volgende gevallen:

  1. Onjuist gebruik van een eigen deleter: Als de aangepaste deleter de toegewezen bron niet correct vrijmaakt (bijvoorbeeld delete in plaats van delete[] voor arrays of het niet aanroepen van de juiste vrijgafunctie).

    #include <memory>
    #include <iostream>
    
    struct MyDeleter {
        void operator()(int* ptr) const {
            // FOUT: moet delete[] zijn, niet delete
            delete ptr;
            std::cout << "Onjuist deleter aangeroepen" << std::endl;
        }
    };
    
    int main() {
        // Array alloceren, maar onjuiste deleter gebruiken
        std::unique_ptr<int, MyDeleter> ptr(new int[10], MyDeleter());
        // Gealloceerde array wordt niet volledig vrijgemaakt bij het verlaten van scope
        return 0;
    }
    
  2. Doorgeven van een rauwe pointer uit unique_ptr aan een functie die vervolgens het eigendom overneemt en niet vrijmaakt: Eigendom moet expliciet worden doorgegeven met std::move. Als je get() of een rauwe pointer doorgeeft en vervolgens niet voor vrijgave zorgt, kan dit leiden tot geheugenlekken.

    #include <memory>
    #include <iostream>
    
    void process_and_lose(int* raw_ptr) {
        // Functie vergeet delete raw_ptr
        std::cout << "Processing " << *raw_ptr << std::endl;
        // Geheugenlek!
    }
    
    int main() {
        std::unique_ptr<int> ptr(new int(42));
        int* raw = ptr.get();
        process_and_lose(raw);
        // ptr beheert nog steeds het geheugen, maar raw_ptr is nu een wees
        // In dit voorbeeld is er geen lek omdat ptr het vrijmaakt
        // Maar als ptr was reset of hergebruikt vóór de call, zou er een lek ontstaan
        return 0;
    }
    

    Verbeterd voorbeeld met potentieel geheugenlek (als eigendom wordt doorgegeven maar de functie niet vrijmaakt):

    #include <memory>
    #include <iostream>
    
    void function_that_takes_ownership_and_leaks(int* owned_ptr) {
        // Verondersteld dat owned_ptr nu eigendom is van deze functie
        std::cout << "Eigendom overgenomen en gelekt: " << *owned_ptr << std::endl;
        // Geheugenlek: owned_ptr wordt niet verwijderd
    }
    
    int main() {
        std::unique_ptr<int> ptr(new int(100));
        // Doorgeven van eigendom van rauwe pointer
        function_that_takes_ownership_and_leaks(ptr.release());
        // ptr is nu leeg, zijn resource (pointer) wordt niet automatisch vrijgegeven
        return 0;
    }
    
  3. Exceptions tussen geheugenallocatie en wrapping in unique_ptr: Hoewel std::make_unique dit voorkomt, kan direct gebruik van new gevolgd door unique_ptr leiden tot een lek als er een uitzondering optreedt tussen de twee.

    #include <memory>
    #include <vector>
    
    class Resource { public: Resource() { std::cout << "Resource created" << std::endl;} ~Resource() { std::cout << "Resource destroyed" << std::endl;} };
    void might_throw() { throw std::runtime_error("Oeps!"); }
    
    int main() {
        Resource* res = new Resource(); // Geheugen toewijzen
        try {
            might_throw(); // Hier treedt een uitzondering op
            std::unique_ptr<Resource> ptr(res); // Deze regel wordt niet bereikt
        } catch (const std::runtime_error& e) {
            std::cerr << "Vang exception: " << e.what() << std::endl;
            // res* is niet ingepakt in unique_ptr en niet verwijderd
            // Dit leidt tot een lek!
        }
        // Correcte manier: std::make_unique<Resource>() of std::unique_ptr<Resource> ptr(new Resource());
        return 0;
    }
    

Over het algemeen is geheugenlek bij correct gebruik van std::unique_ptr zeer onwaarschijnlijk, omdat het hoofddoel automatische resource management is, dat lekken in typische scenario's voorkomt. Problemen ontstaan wanneer je buiten de standaardpraktijken handelt (eigen deleters, release(), interactie met rauwe pointers).