(Решенная ошибка пользователя) c ++ 11 make_shared <t>(новый класс) утечка памяти - PullRequest
0 голосов
/ 03 мая 2020

Я искал интеллектуальные указатели, проводил модульное тестирование, как они управляют памятью, и обнаружил неожиданную проблему, которую рекомендуют делать все примеры, но это создает для меня огромную утечку памяти.

Это, кажется, происходят, когда я использую класс, у которого есть конструктор, который строится из другой копии того же класса. Я приведу пример.

Если у меня есть такой класс, как:

Class foo{
public:
    //Ignore unsafe practices here
    HeavyInMemory* variable;

    foo(){
        variable = new HeavyInMemory();
    }

    foo(foo* copyThis){
        variable  = nullptr;
        if(copyThis){
            variable = new HeavyInMemory(copyThis->variable);
        }
    }

    ~foo(){
        delete variable;
    }
}

, я обнаружу, что получу огромную утечку памяти, потому что std :: make_shared не может определить разницу между make_shared (args) и make_shared (new T)

Main(){
    for(int i =0; i < 100; i++{
        //Should not leak, if I follow examples of how to use make_shared
        auto test = make_shared<foo>(new foo());
    }

    //Checking memory addresses these do not match, checking total program memory use, leaks like a 
    //sieve.
}
  • Я что-то не так понимаю?
  • Не учитывают ли примеры только то, что большинство используют примитивные типы в качестве примеров, а не классов.
  • Поддерживает ли c ++ 11 формат make_shared (new T), даже если я вижу старый такие книги, как книги Скотта Мейерса 1992 года. Это просто не имеет смысла.

Кроме того, зачем вам использовать make_shared (new T) вместо make_shared (args)? Я видел пару потоков, где люди спрашивали об этом здесь, но ни один из них, по-видимому, не ответил на вопрос с примером кода.

//As they mainly say code compiler order causes the leak but in my example this would still leak:
auto originalObject = new foo();
auto expectedDestructorWhenOutofScope = make_shared<foo>(originalObject);

//I have found if I give if the object instead it doesn't leak, but this is getting into the realms of
//hacks that may sometimes work
auto originalObject = new foo();
auto expectedDestructorWhenOutofScope = make_shared<foo>(*originalObject);

РЕДАКТИРОВАТЬ: Благодаря Игорю Тандетнику, я теперь вижу, что я использую make_shared совершенно неправильно. Это следует использовать как конструктор. Еще раз спасибо Игорь, я ценю это.

//Create new
auto expectedDestructorWhenOutofScope = make_shared<foo>();

//Use object already created
std::shared_ptr<Object> p2(new foo())
...