使用unique_ptr作为类成员,为什么它存在内存泄漏?

问题描述 投票:0回答:1

我正在练习unique_ptr的自定义删除器,根据我对unique_ptr的有限经验,它应该在代码中的fclose()之后自动调用析构函数,但事实并非如此。我在网上搜索了很长时间,但没有用。请帮助或尝试提供有关此问题的一些想法。提前致谢。

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;
    }
c++11 memory-leaks smart-pointers unique-ptr
1个回答
1
投票

非数组]的默认删除器> unique_ptr执行:

    delete ptr;

在您自己的删除器中,您仅在A类实例上调用shutdowndelete丢失,这会导致内存泄漏。

    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();
        }
        //...
    };
© www.soinside.com 2019 - 2024. All rights reserved.