我正在练习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;
}
非数组]的默认删除器> unique_ptr
执行:
delete ptr;
在您自己的删除器中,您仅在A类实例上调用
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();
}
//...
};