4

我在 Visual Studio Pro 2012 上使用 std::thread 的这个简单代码有内存泄漏:

#include <thread>

void f(){}

int main(){
    std::thread t(f);
    t.join();
    _CrtDumpMemoryLeaks();
    return 0;}

Win32 输出:

Detected memory leaks!
Dumping objects ->
{293} normal block at 0x00A89520, 44 bytes long.
 Data: <                > 01 00 00 00 00 00 00 00 00 00 00 00 0A 00 00 00 
Object dump complete.

x64 输出:

Detected memory leaks!
Dumping objects ->
{293} normal block at 0x00000000003FCB00, 72 bytes long.
 Data: <                > 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
Object dump complete.

如果我注释 main 方法的前两行,我就没有内存泄漏。

它从何而来 ?

编辑:该代码仍然存在泄漏:

#include <thread>

void f(){}

int main(){
    {
        std::thread t(f);
        t.join();
    }
    _CrtDumpMemoryLeaks();
    return 0;}
4

4 回答 4

9

CrtDumpMemoryLeaks 是出了名的不可靠。很可能是标准库在您第一次使用 std::thread 时故意泄漏一次性分配。要确定是否存在真正的内存泄漏,请尝试以下操作:

for (int i = 0; i < LIMIT; ++i) {
  std::thread t(f); t.join();
}
_CrtDumpMemoryLeaks();

然后查看泄漏大小是否随着 LIMIT 的增加而增加。如果没有,那你很好。

于 2013-05-23T10:24:56.603 回答
4

当您转储泄漏时,线程析构函数尚未运行。你应该试试:

int main()
{
  {
    std::thread t(f);
    t.join();
  }
  _CrtDumpMemoryLeaks();
  return 0;
}
于 2013-05-23T10:18:52.310 回答
0

可能是因为线程对象分配了一些数据,并且当您转储内存时析构函数尚未运行,它被视为泄漏。

尝试将线程对象、创建和连接放在一个单独的函数中。

于 2013-05-23T10:17:41.807 回答
0

你不应该在那个地方调用 CrtDumpMemoryLeaks——或者如果你确实接受了伪泄漏。

静态对象的析构函数尚未运行,此类对象可以位于内存中。如果您使用 MFC,它将从 AFX_STATE 对象的 dtor 运行泄漏转储,这通常太晚以至于只能看到真正的泄漏。

同时,您可以使用_crtBreakAlloc查看该块的分配位置,我敢打赌,调用堆栈将引导您进入 RTL 区域中的一些函数局部静态,您甚至可以在其 dtor 上设置断点以查看它实际上释放了内存在你的垃圾场之后。

于 2013-05-29T00:23:30.683 回答