【发布时间】:2014-09-30 21:36:49
【问题描述】:
我在玩弄 C++,其中有一段“可重新启动”的代码。也就是说:
class handler {
public:
virtual ~handler() {}
virtual response handle(request &req) = 0;
};
response dispatch(request &req, handler &hnd) {
try {
return(hnd.handle(req));
} catch(handler &rep) {
return(dispatch(req, rep));
}
}
然后,在另一部分代码中:
static response serve(request &req) {
throw(resp::message("Merdel", {"Test"}));
}
其中resp::message 是handler 的子类。
这似乎工作正常,但是当我用 Valgrind 运行它时,它告诉我这会泄漏内存:
==2609== 352 bytes in 11 blocks are definitely lost in loss record 12 of 16
==2609== at 0x4C270FE: memalign (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2609== by 0x4010BEF: tls_get_addr_tail (dl-tls.c:529)
==2609== by 0x401110F: __tls_get_addr (dl-tls.c:767)
==2609== by 0x668FC9B: __cxa_get_globals (eh_globals.cc:63)
==2609== by 0x668F5EE: __cxa_allocate_exception (eh_alloc.cc:132)
==2609== by 0x61DDA5E: serve(arw::request&) (arwtest.ashc:7)
==2609== by 0x640E18B: arw::funhandler::handle(arw::request&) (arw.cpp:95)
==2609== by 0x640E1C5: arw::dispatch(arw::request&, arw::handler&) (arw.cpp:100)
==2609== by 0x640E487: arw::dispatch(ashd::request const&, arw::handler&) (arw.cpp:119)
==2609== by 0x61DDBA7: _htstart (arwtest.ashc:11)
==2609== by 0x403CCD: servehtstart (request.c:228)
==2609== by 0x4040C5: servereq (request.c:303)
serve(arw::request&) (arwtest.ashc:7) 是上面列出的serve 函数。
为什么会泄漏内存?我的理解是 C++ 运行时应该自动为我释放这些异常(而且我也没有能力手动释放它们,对吧?),那么是什么原因导致它不释放呢?
我确实找到了 these two 以前关于类似主题的问题,但它们似乎不适用于这里,因为它们仅在特殊情况下处理单个泄漏的异常,而此代码会泄漏每个请求的异常(请注意,有 11 个单独的块被泄露;这是因为我在此测试期间运行了此测试功能 11 次。
编辑:我不知道它是否相关,但可能值得注意的是,回溯中的servehtstart 和servereq 是纯C 程序中的函数。 _htstart 及以上是来自dlopen()ed 共享对象的 C++ 代码。也可能相关的是,只有此共享对象的 dlopen 才能将 libstdc++ 带入进程。
【问题讨论】:
-
你的节目结局如何?
-
@quantdev:此特定代码在单独的线程中运行,该线程在
servereq返回后终止。在此示例中,每个线程都会引发这些异常之一。程序作为一个整体结束,因为我发送它SIGTERM,它捕获并退出运行它的线程中的主循环。另外,请参阅问题的编辑。 -
线程本地存储没有被清理。这可能没问题。
-
@DavidSchwartz:如果我创建的每个线程都有泄漏,这似乎不太好。如何确保 TLS 得到清理?
-
@Dolda2000 检查堆栈中显示的函数,看看它们何时/如何分配 TLS 以及何时/如何清理它。
标签: c++ memory-leaks