Назад к вопросам
Middle+
85
questionbank

Как сделать так, чтобы в shared_ptr происходили утечки памяти?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

При циклической зависимости между объектами, управляемыми shared_ptr.

Пример: Объект A имеет shared_ptr на объект B, а объект B имеет shared_ptr на A. При удалении ссылок на эти объекты извне, их счетчики ссылок никогда не станут нулевыми, так как каждый из них удерживает ссылку на другого.

#include <memory>
#include <iostream>

struct B; // Объявление для избежания циклической зависимости в заголовочных файлах

struct A {
    std::shared_ptr<B> b_ptr; // shared_ptr на B

    ~A() {
        std::cout << "Объект A уничтожен" << std::endl;
    }
};

struct B {
    std::shared_ptr<A> a_ptr; // shared_ptr на A

    ~B() {
        std::cout << "Объект B уничтожен" << std::endl;
    }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();

    a->b_ptr = b; // A ссылается на B
    b->a_ptr = a; // B ссылается на A

    // При выходе из main, shared_ptr a и b будут уничтожены,
    // но связанные объекты A и B не будут уничтожены из-за циклической зависимости.
    // Это приводит к утечке памяти!

    return 0;
}

Как избежать: использовать weak_ptr для одного из указателей в циклической зависимости. weak_ptr не увеличивает счетчик ссылок.

#include <memory>
#include <iostream>

struct B;

struct A {
    std::shared_ptr<B> b_ptr;

    ~A() {
        std::cout << "Объект A уничтожен" << std::endl;
    }
};

struct B {
    std::weak_ptr<A> a_ptr; // Теперь weak_ptr

    ~B() {
        std::cout << "Объект B уничтожен" << std::endl;
    }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();

    a->b_ptr = b;
    b->a_ptr = a; // Используем weak_ptr

    // Теперь при выходе из main, a и b будут уничтожены,
    // счетчик ссылок A станет 0 (поскольку weak_ptr не увеличивает его),
    // A будет уничтожен, затем счетчик ссылок B станет 0, и B будет уничтожен.
    // Утечки памяти нет.

    return 0;
}