Используйте unique_ptr в качестве члена класса. Почему существует утечка памяти? - PullRequest
0 голосов
/ 05 апреля 2020

Я практикую пользовательское удаление unique_ptr, в моем ограниченном опыте с unique_ptr, он должен автоматически вызывать деструктор после fclose() в моем коде, но это не так. Я долго ищу на net, но бесполезно. Пожалуйста, помогите или попробуйте дать некоторые идеи по этому вопросу.
Заранее спасибо.

valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./a.out

основная информация:

==6063== HEAP SUMMARY:
==6063==     in use at exit: 40 bytes in 1 blocks
==6063==   total heap usage: 3 allocs, 2 frees, 73,296 bytes allocated
==6063== 
==6063== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==6063==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6063==    by 0x10909C: B::Init() (aa.cc:29)
==6063==    by 0x108E82: main (aa.cc:44)
==6063== 
==6063== LEAK SUMMARY:
==6063==    definitely lost: 40 bytes in 1 blocks
==6063==    indirectly lost: 0 bytes in 0 blocks
==6063==      possibly lost: 0 bytes in 0 blocks
==6063==    still reachable: 0 bytes in 0 blocks
==6063==         suppressed: 0 bytes in 0 blocks

мой код

 class A {
    public:
        A(const string& _path) : m_path(_path) {};
        ~A() { }
        bool start() {
            m_fp = fopen(m_path.c_str(), "r");
            return m_fp != nullptr;
        }
        void shutdown() { fclose(m_fp); }
    private:
        string m_path;
        FILE *m_fp;
    };
    class B {
    public:
        B(const string &_path) : m_path(_path) { }
        ~B() { }
        void Init() { m_Amember.reset(new A(m_path)); }; // memory leak, why?
        bool Start() { return m_Amember->start(); }
    private:
        struct ResFree {
            void operator()(A* arg) {
                arg->shutdown();
            }
        };
        string m_path;
        unique_ptr<A, ResFree> m_Amember;
    };

    int main() {
        B Instance("kk.txt"); // kk.txt exists
        Instance.Init();
        if (!Instance.Start()) {
            cout << "Client start failed " << endl;
        }
        return 0;
    }

1 Ответ

1 голос
/ 05 апреля 2020

Средство удаления по умолчанию для без массива unique_ptr выполняет:

    delete ptr;

В своем собственном устройстве удаления вы вызываете shutdown только для экземпляра класса. delete отсутствует, что приводит к утечке памяти.

    struct ResFree {
        void operator()(A* arg) {
            arg->shutdown();
            delete arg;
        }
    };

Но IMHO shutdown должен вызываться внутри деструктора класса A. Тогда пользовательское удаление не является действительно необходимым.

 class A {
    public:
        A(const string& _path) : m_path(_path) {};

        ~A() { 
           if (m_fp)
             shutdown();
        }
        //...
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...