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:
-
Ö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
deleteyerinedelete[]ç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; } -
unique_ptr'den alınan ham göstericinin, sahipliği devralan ve serbest bırakmayan bir fonksiyona geçirilmesi: Sahiplik, açıkçastd::moveile yapılmalıdır. Eğerget()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; } -
Bellek tahsisi ile
unique_ptriçine sarma arasında istisnalar:std::make_uniquebunu önlerken, doğrudannewkullanımı ve ardındanunique_ptryapı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).