【问题标题】:Visual C++ 2013 std::string memory leakVisual C++ 2013 std::string 内存泄漏
【发布时间】:2015-03-31 15:01:09
【问题描述】:

在开发专有应用程序期间。我注意到内存泄漏,与 MS Visual C++ 2013 更新 4 中的 std::string 相关。

看看以下导致内存泄漏的(基本)代码原型:

static std::string MemoryLeakTest()
{
    static size_t const test_size = 2002;
    std::unique_ptr<char[]> result1(new char[test_size]);
    std::string result2(result1.get(), test_size);
    return result2;
}

通过以下方式调用它:

std::string const testML = MemoryLeakTest();
std::cout << testML << std::endl;

是我做错了什么,还是 Visual C++ STL 中的内存泄漏?

附:这是显示 VLD 检测到的内存泄漏的 DebugView 输出:

[11140] WARNING: Visual Leak Detector detected memory leaks!
[11140] ---------- Block 3 at 0x00A95620: 2002 bytes ----------
[11140]   Leak Hash: 0x1DA884B6, Count: 1, Total 2002 bytes
[11140]   Call Stack (TID 9568):
[11140]     0x0FF5C260 (File and line number not available): MSVCR120D.dll!operator new
[11140]     f:\dd\vctools\crt\crtw32\stdcpp\newaop.cpp (6): TestCpp.exe!operator new[] + 0x9 bytes
[11140]     c:\work\testcpp\testcpp.cpp (307): TestCpp.exe!MemoryLeakTest + 0xA bytes
[11140]     c:\work\testcpp\testcpp.cpp (401): TestCpp.exe!wmain + 0x9 bytes
[11140]     f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (623): TestCpp.exe!__tmainCRTStartup + 0x19 bytes
[11140]     f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (466): TestCpp.exe!wmainCRTStartup
[11140]     0x75557C04 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0x24 bytes
[11140]     0x77C4B54F (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x8F bytes
[11140]     0x77C4B51A (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x5A bytes
[11140]   Data:

【问题讨论】:

  • 你怎么知道是 std::string 导致了泄漏?
  • 您的代码具有未定义的行为,因为您正在读取未初始化的值。
  • 你是如何确定这段代码泄露的?
  • @wonkorealtime:该解决方案已使用 Visual Leak Detector 进行了测试,它报告内存已分配但未释放的块。出于某种原因,我不能总是重现它。它有时会发生(?)
  • 按照 erol 的建议使用 _CrtDumpMemoryLeaks,我没有从这段代码中得到任何泄漏。

标签: c++ c++11 memory-leaks


【解决方案1】:

用 Deleaker 尝试过你的代码,但没有发现任何泄漏。

然后尝试了这段代码:

while (true)
{
    std::string const testML = MemoryLeakTest();
    std::cout << testML << std::endl;
}

任务管理器显示内存使用保持不变:没有泄漏。

我认为这是VLD中的一个bug,你可以发现std::unique_ptr确实释放了内存,调试的时候就进入,看看:

~unique_ptr() _NOEXCEPT
    {   // destroy the object
    _Delete();
    }

走得更远:

void _Delete()
    {   // delete the pointer
    if (this->_Myptr != pointer())
        this->get_deleter()(this->_Myptr);
    }
};

走得更远:

void operator()(_Ty *_Ptr) const _NOEXCEPT
    {   // delete a pointer
    static_assert(0 < sizeof (_Ty),
        "can't delete an incomplete type");
    delete[] _Ptr;
    }
};

啊哈,delete[] 被调用了!

【讨论】:

  • 是的,我的最终结论是一样的 - 这可能是 VLD 中的错误。非常感谢您的时间和分析。
【解决方案2】:

电话

std::unique_ptr<char[]> result1(new char[test_size]);

是正确的。棘手的部分是不要写std::unique_ptr&lt;char&gt;,它也会编译并可能导致内存泄漏(unique_ptr 调用delete 以释放资源。当使用new[] 初始化时,我们需要指示unique_ptr 调用正确的delete[])。

std::string 构造函数调用也可以,而且不太可能存在内存泄漏。 std::string 可以用相同的方式从 C 风格的指针初始化。

我在您的代码 sn-p 中没有看到任何内存泄漏。你怎么知道是内存泄漏?

【讨论】:

  • 这不再是真的,是吗?最新标准在 shared_ptr 和 unique_ptr 中自动处理数组删除。
  • @Robinson 没错,MSDN 文档指出:(部分特化 unique_ptr管理用 new[] 分配的数组对象,并具有默认删除器 default_delete,专门用于调用删除[] _Ptr.) msdn.microsoft.com/en-us/library/ee410601.aspx
  • 仍然对 std::unique_ptr 和 std::unique_ptr 之间的区别摸不着头脑。我想它们编译成相同的东西,或者后者实际上是指向指针的指针?那会让它崩溃(但它不适合我)。
  • @Robinson 他们都包装了char*unique_ptr&lt;char&gt;delete 处理该指针,unique_ptr&lt;char[]&gt;delete[] 处理它。
  • @Robinson:假设你有一个new char 和一个new char[]。以后如何删除每一个?现在,unique_ptr 以后要如何删除每一个?
猜你喜欢
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 2011-03-26
  • 2018-01-03
  • 1970-01-01
  • 2014-08-18
  • 2014-04-12
相关资源
最近更新 更多