Sobes.tech
Middle
183

C++-та unique_ptr қолданғанда жадының ағуы қалай болуы мүмкін?

AI-дан жауап

sobes.tech AI

std::unique_ptr қолданғанда жадының ағуы келесі жағдайларда мүмкін:

  1. Өздігінен жүзеге асырылған жоюшыны (Deleter) дұрыс қолданбау: Егер қолданушының жоюшысы бөлінген ресурсты дұрыс босатпаса (мысалы, массив үшін delete[] орнына delete шақыру немесе сәйкес босату функциясын қолданбау).

    #include <memory>
    #include <iostream>
    
    struct MyDeleter {
        void operator()(int* ptr) const {
            // Қате: delete[] орнына delete қолдану керек
            delete ptr;
            std::cout << "Қате жоюшы шақырылды" << std::endl;
        }
    };
    
    int main() {
        // Массивті бөлдік, бірақ дұрыс емес жоюшыны қолдандық
        std::unique_ptr<int, MyDeleter> ptr(new int[10], MyDeleter());
        // Массив ретінде бөлінген жады толық босатылмайды
        return 0;
    }
    
  2. unique_ptr-тен алынған көрсеткішті басқа функцияға беру, ол иелігін қабылдап, босатпаса: Иелікті айқын түрде std::move көмегімен беру керек. Егер get() немесе сыры көрсеткішті берсеңіз және оны басқа жерде босатпасаңыз, жады ағуы мүмкін.

    #include <memory>
    #include <iostream>
    
    void process_and_lose(int* raw_ptr) {
        // delete-ді ұмытқан функция
        std::cout << "Өңдеу " << *raw_ptr << std::endl;
        // Жадының ағуы!
    }
    
    int main() {
        std::unique_ptr<int> ptr(new int(42));
        int* raw = ptr.get();
        process_and_lose(raw);
        // ptr әлі басқаруда, бірақ raw көрсеткіш жетім
        // Бұл жағдайда ағу болмайды, себебі ptr босататын болады
        // Егер ptr басқаға ауыстырылса немесе жойылса, ағу мүмкін
        return 0;
    }
    

    Иелігін беру және мүмкін болатын ағуды көрсететін түзетілген мысал (егер иелігін берсеңіз, бірақ функция босатпаса):

    #include <memory>
    #include <iostream>
    
    void function_that_takes_ownership_and_leaks(int* owned_ptr) {
        // Бұл көрсеткіш енді осы функцияға тиесілі деп есептеледі
        std::cout << "Иелікті алу және ағызу: " << *owned_ptr << std::endl;
        // Ағу: owned_ptr босатылмайды
    }
    
    int main() {
        std::unique_ptr<int> ptr(new int(100));
        // Иелігін сыры көрсеткіш арқылы береміз
        function_that_takes_ownership_and_leaks(ptr.release());
        // ptr бос, оның ресурсы (көрсеткіш) автоматты түрде босатылмайды
        return 0;
    }
    
  3. Жады бөлінгеннен және оны unique_ptr-ке орау арасында қателіктер: std::make_unique бұны болдырмайды, бірақ new-ды тікелей қолдану және одан кейін unique_ptr құру қателіктерге әкелуі мүмкін, егер арасында қате орын алса.

    #include <memory>
    #include <vector>
    
    class Resource { public: Resource() { std::cout << "Ресурс жасалды" << std::endl;} ~Resource() { std::cout << "Ресурс жойылды" << std::endl;} };
    void might_throw() { throw std::runtime_error("Қате!" ); }
    
    int main() {
        Resource* res = new Resource(); // Жады бөлдік
        try {
            might_throw(); // Мұнда қате пайда болады
            std::unique_ptr<Resource> ptr(res); // Бұл жол орындалмайды
        } catch (const std::runtime_error& e) {
            std::cerr << "Қабылданды: " << e.what() << std::endl;
            // res* бос емес және босатылмаған
            // Бұл ағуға әкеледі!
        }
        // Дұрыс тәсіл: std::make_unique<Resource>() немесе std::unique_ptr<Resource> ptr(new Resource());
        return 0;
    }
    

Жалпы алғанда, std::unique_ptr қолданғанда жады ағуы өте сирек кездеседі, себебі оның негізгі мақсаты — ресурстарды автоматты басқару, ол типтік сценарийлерде ағуды болдырмайды. Мәселелер оның стандартты қолдану шегінен шыққанда пайда болады (өздігінен жүзеге асырылған жоюшы, release(), сыры көрсеткіштермен жұмыс істеу).