【问题标题】:Use unique_ptr as a class member, Why does it exist memory leaking?使用unique_ptr作为类成员,为什么会存在内存泄漏?
【发布时间】:2020-07-17 10:12:30
【问题描述】:

我正在练习 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】:

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

        delete ptr;
    

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

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

    但是恕我直言,shutdown 应该在 A 类的析构函数中调用。那么自定义删除器就不是必需的了。

     class A {
        public:
            A(const string& _path) : m_path(_path) {};
    
            ~A() { 
               if (m_fp)
                 shutdown();
            }
            //...
        };
    

    【讨论】:

    • 是的,你是对的。我只是在使用一个必须显式调用像shutdown 这样的函数来释放资源的库。我想模拟这种情况。
    猜你喜欢
    • 2011-10-25
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    相关资源
    最近更新 更多