我在一个大型项目中使用tcmalloc已经有几个月了,到目前为止,我必须说我对tcmalloc非常满意,最重要的是它的大量特性允许跟踪内存泄漏并将其删除。
在过去的几周里,虽然我们在应用程序中遇到了随机崩溃,但我们找不到随机崩溃的根源。在非常特殊的情况下,当应用程序崩溃时,我们发现其中一个应用程序线程的堆栈已完全损坏。有几次我发现线程被困在tcmalloc::PageHeap::AllocLarge()中,但是由于没有链接tcmalloc的调试符号,我无法理解问题是什么。
经过近一周的调查,今天我尝试了最简单的方法:从linkage中删除tcmalloc以避免使用它,只是为了看看发生了什么。好。。。我终于发现问题出在哪里了,而违规代码看起来非常像这样:

   void AllocatingFunction()
   {
       Object object_on_stack;
       ProcessObject(&object_on_stack);

   }

   void ProcessObject(Object* object)
   {
       ...
       // Do Whatever
       ...
       delete object;
   }

使用libc,应用程序仍然崩溃,但我终于看到我正在调用一个在堆栈上分配的对象的delete。
我仍然搞不懂的是,为什么tcmalloc会让应用程序继续运行,而不管这个非常危险(如果不是完全错误的话)的对象释放,以及在allocationfunction结束时,object_on_stack超出作用域时的双重释放。事实上,违规代码可以被反复调用,而不需要任何潜在的厌恶。
我知道,如果使用不当,内存释放是“未定义的行为”之一,但令我惊讶的是,“标准”libc和tcmalloc之间的行为是如此不同。
有没有人对tcmalloc为什么保持应用程序运行有某种解释?
提前谢谢:)
祝您有个美好的一天

最佳答案

非常危险(如果不是完全错误的话)的对象释放
好吧,我不同意,这是完全错误的,既然你调用UB,任何事情都可能发生。
这在很大程度上取决于tcmalloc代码对释放的实际操作,以及它如何在该位置使用堆栈周围的(可能是垃圾)数据。
我也见过tcmalloc在这种情况下崩溃,以及glibc进入无限循环。你看到的只是巧合。

07-27 23:16