Visual Studio中的内存泄漏问题

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.

如果我注释掉主方法的前两行,就不会有内存泄漏。
这是怎么回事?
编辑:即使使用这段代码,泄漏仍然存在。
#include <thread>

void f(){}

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

9

CrtDumpMemoryLeaks 臭名昭著的不可靠。当您第一次使用 std::thread 时,标准库可能会有意地泄漏一次性分配的内存。要查找是否存在真正的内存泄漏,请尝试以下操作:

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

然后,看看泄漏大小是否随着限制增加而增加。如果没有增加,那么就没问题了。


你是对的,泄漏不会随着启动的线程数量增加而增加。 - Arnaud
@Arnaud 那可能是一次性静态分配,没什么可担心的。 - Some programmer dude

4

当您转储泄漏时,线程析构函数尚未运行。您可以尝试:

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

我也曾这么想,但内存泄漏仍然存在。 - Arnaud
@Arnaud 但是你应该使用这个版本编辑问题。在你发布的那个版本中,不清楚这些对象是否仍然需要。 - Daniel Daranas

0

你不应该在那个位置调用CrtDumpMemoryLeaks -- 或者如果你接受伪泄漏的话。

静态对象的析构函数尚未运行,这些对象可能会停留在内存中。如果你使用MFC,它将从AFX_STATE对象的dtor中运行泄漏转储,通常晚到足以只看到真正的泄漏。

同时,你可以使用_crtBreakAlloc来查看分配该块的位置,我敢打赌调用堆栈会引导你到RTL领域中的一些函数局部静态变量,并且你甚至可以在它的dtor上设置断点,以便在你的转储之后稍微释放内存。


0

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

尝试将线程对象、创建和加入放在单独的函数中。


如果我将线程部分放在一个函数中,也会发生这种情况:void g(){std::thread t(f);t.join();} - Arnaud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接