std :: string operator +()内存泄漏?

时间:2011-09-02 13:45:17

标签: c++ string stl memory-leaks valgrind

我很担心,因为我写了一个小应用程序,如果我相信valgrind(我实际上做了什么),似乎存在内存泄漏:

==9321== 251 bytes in 7 blocks are definitely lost in loss record 1 of 1
==9321==    at 0x402569A: operator new(unsigned int) (vg_replace_malloc.c:255)
==9321==    by 0x40D3D05: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.13)
==9321==    by 0x40D4977: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned int) (in /usr/lib/libstdc++.so.6.0.13)
==9321==    by 0x40D57AC: std::string::reserve(unsigned int) (in /usr/lib/libstdc++.so.6.0.13)
==9321==    by 0x40D5EE6: std::string::operator+=(char) (in /usr/lib/libstdc++.so.6.0.13)
==9321==    by 0x804E113: xl2::TextParser::getNextLfLine() (TextParser.cpp:162)
==9321==    by 0x804BFD5: xl2::UsbTree::parseStringInfo(xl2::TextParser&, std::string&, std::string&) (UsbTree.cpp:362)
==9321==    by 0x804B881: xl2::UsbTree::parseDevicesFile(std::string) (UsbTree.cpp:204)
==9321==    by 0x804B34E: xl2::UsbTree::updateTree() (UsbTree.cpp:70)
==9321==    by 0x804E2E4: scan(std::string) (testUsbTree.cpp:75)
==9321==    by 0x804E6CC: executeCommand(std::string) (testUsbTree.cpp:132)
==9321==    by 0x804E8F6: hushLoop() (testUsbTree.cpp:153)

这是有问题的功能:

/**
 * Returns the next line separated by UNIX style LF
 * @return The next line separated by UNIX style LF
 */
std::string TextParser::getNextLfLine()
{
    std::string line;   // The builded line

    while(this->hasMoreToken())
    {
        line += this->m_pText[this->m_iTokenLocation++];

        // Check if we have just seen a CR/LF character
        if(this->m_pText[this->m_iTokenLocation - 1] == '\n')
            return line;
    }

    return line;
}

程序通过离开主函数(没有调用exit())正确终止。

我只是不明白为什么会有内存泄漏。当我的字符串被复制到堆栈中时,原来的字符串应该在函数离开时被清除,对吗?或者错误可能更高?在顶级我还将返回值分配给一个局部变量,然后将该字段作为字段放入一个对象中(通过复制)......

所以我想知道泄漏是来自标准库还是valgrind,这真的很令人惊讶!

非常感谢任何未泄露内存的指示:-p!

3 个答案:

答案 0 :(得分:10)

引用Valgrind FAQ

  

使用GCC 2.91,2.95,3.0和3.1,使用带有-D__USE_MALLOC的STL编译所有源。谨防!从版本3.3开始,这已从GCC中删除。

     

使用GCC 3.2.2及更高版本,您应该在运行程序之前导出环境变量GLIBCPP_FORCE_NEW。

     

使用GCC 3.4及更高版本,该变量已将名称更改为GLIBCXX_FORCE_NEW。

还在GCC FAQ

中讨论过

答案 1 :(得分:8)

我不会过分担心STL漏洞。

默认的STL分配器(用于gcc)使用巧妙的技巧来最大化Valgrind经常报告泄漏的效率。值得注意的是,它会汇集内存,这意味着它会在您清除string时保留内存,并且可能会在您下次插入mapvector时重复使用。

我不认为池本身在程序结束时被妥善处理,可能是为了避免静态破坏命令Fiasco(即,想象池被丢弃然后你请求内存,urk)。因此它泄漏......就在程序结束之前,操作系统强行恢复内存。

答案 2 :(得分:1)

我怀疑正在发生的事情是编译器正在使用NRVO将临时字符串放入其实际返回位置。然后将该返回字符串存储在已分配并从堆中泄漏的对象中。