dimanche 5 avril 2020

Use unique_ptr as a class member, Why does it exist memory leaking?

I am practicing the custom deleter of unique_ptr, in my limited experience with unique_ptr, it should automatically call the destructor after fclose() in my code, but it doesn't. I am searching for a long time on net, but no use. Please help or try to give some ideas about this question.
Thanks in advance.

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

main information:

==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

my code

 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;
    }

Aucun commentaire:

Enregistrer un commentaire