【发布时间】:2013-05-16 09:47:05
【问题描述】:
我已经在一个大型项目中使用 tcmalloc 几个月了,到目前为止,我必须说我对它非常满意,最重要的是它的 HeapProfiling 功能允许跟踪内存泄漏并删除它们。
在过去的几周里,虽然我们的应用程序遇到了随机崩溃,但我们无法找到随机崩溃的根源。在一个非常特殊的情况下,当应用程序崩溃时,我们发现自己的一个应用程序线程的堆栈完全损坏。有几次我发现线程卡在 tcmalloc::PageHeap::AllocLarge() 中,但是由于我没有链接 tcmalloc 的调试符号,所以我无法理解问题所在。
经过近一周的调查,今天我尝试了最简单的事情:从链接中删除tcmalloc以避免使用它,只是为了看看发生了什么。嗯...我终于发现问题出在哪里了,违规代码看起来很像这样:
void AllocatingFunction()
{
Object object_on_stack;
ProcessObject(&object_on_stack);
}
void ProcessObject(Object* object)
{
...
// Do Whatever
...
delete object;
}
使用 libc 应用程序仍然崩溃,但我终于看到我正在对分配在堆栈上的对象调用 delete。
我仍然无法弄清楚为什么 tcmalloc 会保持应用程序运行,而不管这种非常危险(如果不是完全错误)的对象释放,以及当 AllocatingFunction 结束时 object_on_stack 超出范围时的双重释放。事实上,有问题的代码可以被重复调用,而没有任何潜在的可憎之处。
我知道如果使用不当,内存释放是一种“未定义的行为”,但令我惊讶的是“标准”libc 和 tcmalloc 之间的行为如此不同。
有没有人对为什么 tcmalloc 保持应用程序运行有某种洞察力的解释?
提前致谢:)
祝你有美好的一天
【问题讨论】:
-
他们选择了“未定义的行为”来不崩溃。我会依赖这个吗? 见鬼。