【问题标题】:Why does thread-local heap memory not get freed on thread exit?为什么线程局部堆内存在线程退出时没有被释放?
【发布时间】:2011-12-15 16:01:39
【问题描述】:

参考这个结构,发布一个完整的例子有点太大了:

__thread char* buf;
buf = malloc(1000);

Valgrind 说字节“肯定”丢失了。他们不应该只是“仍然可以访问”吗?

【问题讨论】:

    标签: c linux pthreads valgrind


    【解决方案1】:

    因为分配的内存不是线程本地的。它由所有线程共享。

    另一方面,该变量是线程本地的,因此一旦超出范围,分配的内存肯定会丢失(如果其他地方没有该指针的副本..显然没有,因为 valgrind 报告肯定会丢失)

    你必须free它。

    【讨论】:

    • 嗯,是的,它是线程本地的。这就是 __thread 的全部意义所在。
    • 是的。只有堆栈是线程本地的,而不是堆。堆没有理由应该是线程本地的。
    • @mouviciel 您是否有任何支持资源来支持堆永远不是线程本地的说法?我搜索了,但除了你的评论,没有任何迹象表明你是对的。
    • 这只是常识。首先,开发人员很懒惰。存在一个全局堆 aleady,malloc() 使用它。当引入线程时,很容易使用现有的功能。其次,每个线程实现一个堆意味着更多的 RAM 限制,并且可能在线程级别而不是进程级别进行交换。为什么不?但是这个特性能解决什么问题呢?允许悬空malloc()?实现垃圾收集器会更容易。
    • 对于那些认为将__thread 放在指针变量上会使malloc-obtained 块的无知的人,您将其地址存储在其中以某种方式线程本地...是否将auto 放在指针变量使malloc-obtained 块自动存储其地址(变量超出范围后立即释放)?哦对了,所有的本地变量默认都是auto...
    【解决方案2】:

    如果指向块的唯一指针是线程本地的,那么退出线程,你就失去了唯一的指针。

    这意味着它不再可达 = 肯定丢失了。

    【讨论】:

      【解决方案3】:

      您需要通过调用free 显式释放它。

      malloc 分配的堆分配内存在通过调用free 显式释放之前不会被回收。只有堆栈分配的本地存储对象会在线程结束时自动释放。

      这肯定会丢失,因为一旦线程退出,您就没有任何指向分配内存的指针,指向内存的指针是线程堆栈的本地指针,当线程退出时它会被销毁,但是分配的内存是堆内存,不会被释放。

      【讨论】:

        【解决方案4】:

        好吧,正如其他人所说,你必须free它。

        其背后的原因是:所有线程共享一个公共堆,并且从概念上讲,内存“所有权”可以在线程之间传递。一个线程可以 malloc 某些东西,而另一个线程可以释放它。但是,堆不知道谁“拥有”内存,所以当你的线程终止时(即使堆记得哪个线程 malloc 了什么)它不能安全地删除它。

        但是,当你的 进程 终止时,所有的堆内存都被有效地“释放”了——但不是单独的:你的进程的整个堆(可能只是一个大块)被返回到操作系统。

        【讨论】:

        • 这就是问题所在,如果是线程本地存储,线程可以安全地删除它,因为内存与任何人共享其他线程。 (至少在逻辑上不是共享的,另一个线程可能意外地访问内存并不重要,例如通过数组溢出的方法)
        • @Blub :只有 指针 是线程本地的。它实际上指向的不是。 malloc 无法知道您要将其分配给线程本地指针。
        • @Blub:一般情况下,确定内存不能被其他线程访问,就相当于停机问题。因此,您的建议是,根据您的编译器是否可以解决停机问题的特殊情况,有时会释放内存,有时则不会释放内存。现在考虑到双重释放会调用非常危险的未定义行为,并且您无法知道它是否会自动释放,这听起来像是一场灾难!
        【解决方案5】:

        这有点像“味道好”/“少饱”的说法。 Valgrind 是正确的,并且数据“仍然可以访问”。例如,如果数据包含密码,您可以 100% 从堆扫描中提取密码。如果数据以唯一的随机数开头,您可以重新定位它。 Valgrind 意味着你不能再通过指针访问数据。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-11-07
          • 1970-01-01
          • 1970-01-01
          • 2020-04-12
          • 2022-07-08
          • 2016-01-26
          • 2014-06-14
          • 1970-01-01
          相关资源
          最近更新 更多