C++ da unique_ptr ishlatilganda qanday qilib xotira oqishini oldini olish mumkin?
sobes.tech AI
AIdan javob
std::unique_ptr bilanotlarining to'kilishi quyidagi holatlarda yuzaga kelishi mumkin:
-
Maxsus o'chirishchi (Deleter) noto'g'ri ishlatilishi: Agar maxsus o'chirishchi to'g'ri tarzda ajratilgan resursni bo'shatmasa (masalan, massiv uchun
deleteo'rnigadelete[]chaqirmasa yoki mos bo'shatish funksiyasini chaqirmasa).#include <memory> #include <iostream> struct MyDeleter { void operator()(int* ptr) const { // XATO: delete[] bo'lishi kerak, delete emas delete ptr; std::cout << "Noto'g'ri o'chirishchi chaqirildi" << std::endl; } }; int main() { // Massiv ajratildi, ammo noto'g'ri o'chirishchi ishlatilgan std::unique_ptr<int, MyDeleter> ptr(new int[10], MyDeleter()); // Massiv sifatida ajratilgan xotira ptr tashqariga chiqgach to'liq bo'shatilmaydi return 0; } -
unique_ptrdan olingan xom ko'rsatkichni, uni egallagan va bo'shatmaydigan funksiyaga o'tkazish: Egallashni aniqstd::moveyordamida qilish kerak. Agarget()yoki xom ko'rsatkich o'tkazilsa va uni boshqa joyda bo'shatmasangiz, bu xotira oqishiga olib kelishi mumkin.#include <memory> #include <iostream> void process_and_lose(int* raw_ptr) { // Funksiya "delete" ni unutdi std::cout << "Qayta ishlash " << *raw_ptr << std::endl; // Xotira oqishi! } int main() { std::unique_ptr<int> ptr(new int(42)); // Xom ko'rsatkich olamiz int* raw = ptr.get(); process_and_lose(raw); // ptr hali ham xotirani boshqaradi, ammo raw_ptr yolg'onga aylandi // Bu holatda, `ptr` xotirani bo'shatadi, lekin `raw_ptr` bo'sh qoladi // Agar `ptr` oldindan reset qilinsa yoki qayta tayinlansa va funksiya uni o'chirmasa, oqish yuzaga keladi return 0; }To'g'irlangan misol, egallashni o'tkazib yuborgan va oqish ehtimoli bo'lgan holatda:
#include <memory> #include <iostream> void function_that_takes_ownership_and_leaks(int* owned_ptr) { // Bu funksiya endi owned_ptr ga egalik qiladi deb faraz qilamiz std::cout << "Egallash va oqish: " << *owned_ptr << std::endl; // Oqish: owned_ptr o'chirilmaydi } int main() { std::unique_ptr<int> ptr(new int(100)); // Xom ko'rsatkich egallash va o'tkazish function_that_takes_ownership_and_leaks(ptr.release()); // ptr endi bo'sh, uning resursi (ko'rsatkich) avtomatik ravishda bo'shatilmaydi return 0; } -
Xotira ajratish va
unique_ptrga o'rash orasida istisnolar:std::make_uniquebuni oldini oladi, lekin to'g'ridan-to'g'rinewishlatish va keyinunique_ptrkonstruktoridan foydalanish, ular orasida istisno yuzaga kelsa, oqishga olib kelishi mumkin.#include <memory> #include <vector> class Resource { public: Resource() { std::cout << "Resurs yaratildi" << std::endl;} ~Resource() { std::cout << "Resurs yo'q qilindi" << std::endl;} }; void might_throw() { throw std::runtime_error("OOPS!"); } int main() { Resource* res = new Resource(); // Xotira ajratish try { might_throw(); // Bu yerda istisno yuzaga keladi std::unique_ptr<Resource> ptr(res); // Bu satrga yetib borilmaydi } catch (const std::runtime_error& e) { std::cerr << "Uchyotga olindi: " << e.what() << std::endl; // res* unique_ptr ga o'ralmagan va yo'q qilinmagan // Bu oqishga olib keladi! } // To'g'ri usul: std::make_unique<Resource>() yoki std::unique_ptr<Resource> ptr(new Resource()); return 0; }
Umuman olganda, std::unique_ptr bilan to'g'ri foydalanish bilan xotira oqishi juda kam ehtimol, chunki uning asosiy maqsadi resurslarni avtomatik boshqarish va odatiy holatlarda oqishni oldini olishdir. Muammolar uning standart foydalanish chegaralaridan chiqib ketganda yuzaga keladi (maxsus o'chirishchilar, release(), xom ko'rsatkichlar bilan ishlash).