Sobes.tech
Middle

C++'ta unique_ptr kullanırken nasıl bellek sızıntısına izin verilebilir?

sobes.tech yapay zeka

AI'dan gelen yanıt

std::unique_ptr kullanımı sırasında bellek sızıntısı aşağıdaki durumlarda olabilir:

  1. Özelleştirilmiş yok edici (Deleter) yanlış kullanımı: Kullanıcı tanımlı yok edici, tahsis edilen kaynağı düzgün şekilde serbest bırakmıyorsa (örneğin, dizi için delete yerine delete[] çağrısı yapmıyorsa veya uygun serbest bırakma fonksiyonunu çağırmıyorsa).

    #include <memory>
    #include <iostream>
    
    struct MyDeleter {
        void operator()(int* ptr) const {
            // HATA: delete[] olmalı, delete değil
            delete ptr;
            std::cout << "Yanlış yok edici çağrıldı" << std::endl;
        }
    };
    
    int main() {
        // Dizi tahsis edilmiştir, ancak yanlış yok edici kullanılmıştır
        std::unique_ptr<int, MyDeleter> ptr(new int[10], MyDeleter());
        // Dizi olarak tahsis edilen bellek, ptr dışına çıkıldığında tam anlamıyla serbest bırakılmaz
        return 0;
    }
    
  2. unique_ptr'den alınan ham göstericinin, sahipliği devralan ve serbest bırakmayan bir fonksiyona geçirilmesi: Sahiplik, açıkça std::move ile yapılmalıdır. Eğer get() veya ham gösterici geçirilir ve başka yerde serbest bırakılmazsa, bu bellek sızıntısına yol açabilir.

    #include <memory>
    #include <iostream>
    
    void process_and_lose(int* raw_ptr) {
        // Fonksiyon "delete" işlemini unutur
        std::cout << "İşleniyor " << *raw_ptr << std::endl;
        // Bellek sızıntısı!
    }
    
    int main() {
        std::unique_ptr<int> ptr(new int(42));
        // Ham gösterici alınır
        int* raw = ptr.get();
        process_and_lose(raw);
        // ptr hâlâ belleği yönetiyor, ancak raw_ptr yetim kaldı
        // Bu durumda sızıntı yoktur, çünkü ptr belleği serbest bırakır
        // Ama eğer ptr, çağrıdan önce sıfırlanır veya yeniden atanırsa,
        // ve fonksiyon onu silmezse, sızıntı olur
        return 0;
    }
    

    Düzeltilmiş örnek, sahipliği devralıp fonksiyonun serbest bırakmadığı durumda potansiyel sızıntı ile birlikte:

    #include <memory>
    #include <iostream>
    
    void function_that_takes_ownership_and_leaks(int* owned_ptr) {
        // Artık owned_ptr'nin bu fonksiyonun sahibi olduğu varsayılır
        std::cout << "Sahipliği alıp sızdırma: " << *owned_ptr << std::endl;
        // Sızıntı: owned_ptr serbest bırakılmıyor
    }
    
    int main() {
        std::unique_ptr<int> ptr(new int(100));
        // Ham göstericinin sahipliğini devret
        function_that_takes_ownership_and_leaks(ptr.release());
        // ptr artık boş, kaynağı (gösterici) otomatik olarak serbest bırakılmaz
        return 0;
    }
    
  3. Bellek tahsisi ile unique_ptr içine sarma arasında istisnalar: std::make_unique bunu önlerken, doğrudan new kullanımı ve ardından unique_ptr yapıcı kullanımı, arada istisna oluşursa sızıntıya neden olabilir.

    #include <memory>
    #include <vector>
    
    class Resource { public: Resource() { std::cout << "Kaynak oluşturuldu" << std::endl;} ~Resource() { std::cout << "Kaynak yok edildi" << std::endl;} };
    void might_throw() { throw std::runtime_error("Hoppala!"); }
    
    int main() {
        Resource* res = new Resource(); // Bellek tahsisi
        try {
            might_throw(); // Burada istisna oluşur
            std::unique_ptr<Resource> ptr(res); // Bu satır ulaşmaz
        } catch (const std::runtime_error& e) {
            std::cerr << "Yakalanan istisna: " << e.what() << std::endl;
            // res* bir unique_ptr'e sarılmadı ve serbest bırakılmadı
            // Bu, sızıntıya yol açar!
        }
        // Doğru yöntem: std::make_unique<Resource>() veya std::unique_ptr<Resource> ptr(new Resource());
        return 0;
    }
    

Genel olarak, std::unique_ptr'ın doğru kullanımıyla bellek sızıntısı çok düşük olasılıktadır, çünkü temel amacı kaynakları otomatik yönetmek ve tipik senaryolarda sızıntıları önlemektir. Sorunlar, onun standart kullanım sınırlarının dışına çıkıldığında ortaya çıkar (özelleştirilmiş yok ediciler, release(), ham göstericilerle etkileşim).