我正在练习unique_ptr的自定义deleter,在我使用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
的默认deleter执行:
delete ptr;
在您自己的deleter中,您只能在类实例上调用shutdown
。delete
丢失,导致内存泄漏。
struct ResFree {
void operator()(A* arg) {
arg->shutdown();
delete arg;
}
};
但是IMHOshutdown
应该在A
类的析构函数内部调用。那么自定义deleter并不是真正必要的。
class A {
public:
A(const string& _path) : m_path(_path) {};
~A() {
if (m_fp)
shutdown();
}
//...
};