std :: string operator + () утечка памяти? - PullRequest
13 голосов
/ 02 сентября 2011

Я очень волнуюсь, потому что я написал небольшое приложение, и кажется, что если я верю 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 ]

10 голосов
/ 02 сентября 2011

Цитировать Valgrind FAQ

С GCC 2.91, 2.95, 3.0 и 3.1 скомпилируйте весь исходный код, используя STL с -D__USE_MALLOC. Осторожно! Это было удалено из GCC, начиная с версии 3.3.

В GCC 3.2.2 и более поздних версиях вы должны экспортировать переменную среды GLIBCPP_FORCE_NEW до запуска вашей программы.

В GCC 3.4 и более поздних версиях эта переменная сменила имя на GLIBCXX_FORCE_NEW.

Также обсуждается в GCC FAQ

8 голосов
/ 02 сентября 2011

Я бы не слишком беспокоился о протечках STL.

Распределитель STL по умолчанию (для gcc) использует хитрые приемы, чтобы максимизировать эффективность, о которой Valgrind часто сообщает как утечки. В частности, он объединяет память, а это означает, что он хранит память при очистке string и может повторно использовать ее при следующей вставке, например, в map или vector.

Я не думаю, что сам пул должным образом удаляется в конце программы, вероятно, чтобы избежать фиаско Порядка статического уничтожения (т. Е. Представьте, что пул удаляется, и вы затем запрашиваете память, urk). Таким образом, она протекает ... как раз перед тем, как ваша программа заканчивается, и ОС возвращает память обратно принудительно.

1 голос
/ 02 сентября 2011

Я подозреваю, что происходит, если компилятор использует NRVO, чтобы поместить вашу временную строку в ее реальное место возврата. Эта возвращаемая строка затем сохраняется внутри объекта, который выделен и вытек из кучи.

...