首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自tcmalloc的意外行为

来自tcmalloc的意外行为
EN

Stack Overflow用户
提问于 2013-05-16 17:47:06
回答 2查看 1.4K关注 0票数 0

我在一个大型项目中使用tcmalloc已经有几个月了,到目前为止,我必须说我对它相当满意,最重要的是它的HeapProfiling特性,它允许跟踪内存泄漏并删除它们。

然而,在过去的几周里,我们的应用程序经历了随机崩溃,我们找不到随机崩溃的来源。在一种非常特殊的情况下,当应用程序崩溃时,我们发现其中一个应用程序线程的堆栈完全损坏。有几次我发现tcmalloc::PageHeap::AllocLarge()中的线程被卡住了,但是因为我没有链接tcmalloc的调试符号,所以我不能理解是什么问题。

经过近一周的调查,今天我尝试了最简单的方法:将tcmalloc从链接中删除,以避免使用它,只是为了看看发生了什么。好吧..。我终于找到了问题所在,令人不快的代码看起来很像这样:

代码语言:javascript
复制
   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能让应用程序保持运行?

提前感谢:)

祝您今天愉快

EN

回答 2

Stack Overflow用户

发布于 2013-05-16 18:00:35

非常危险(如果不是完全错误的话)对象释放

好吧,我不同意这一点,这是完全错误的,因为你调用了UB,任何事情都可能发生。

这在很大程度上取决于tcmalloc代码在释放时实际做了什么,以及它如何在该位置使用堆栈周围的数据(可能是垃圾)。

我也见过tcmalloc在这种情况下崩溃,以及glibc进入无限循环。你看到的只是巧合。

票数 2
EN

Stack Overflow用户

发布于 2013-07-06 06:20:37

首先,在你的例子中没有双重free。当object_on_stack超出作用域时,没有free调用,只有堆栈指针减少(或者更确切地说,随着堆栈的增长而增加……)。

其次,在删除过程中,TcMalloc应该能够识别来自堆栈的地址不属于程序堆。以下是free(ptr)实现的一部分:

代码语言:javascript
复制
const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
Span* span = NULL;
size_t cl = Static::pageheap()->GetSizeClassIfCached(p);

if (cl == 0) {
    span = Static::pageheap()->GetDescriptor(p);
    if (!span) {
        // span can be NULL because the pointer passed in is invalid
        // (not something returned by malloc or friends), or because the
        // pointer was allocated with some other allocator besides
        // tcmalloc.  The latter can happen if tcmalloc is linked in via
        // a dynamic library, but is not listed last on the link line.
        // In that case, libraries after it on the link line will
        // allocate with libc malloc, but free with tcmalloc's free.
        (*invalid_free_fn)(ptr);  // Decide how to handle the bad free request
        return;
    }

对invalid_free_fn的调用崩溃。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16584109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档