Выявление утечек памяти в C ++ - PullRequest
1 голос
/ 17 июня 2010

У меня есть следующий фрагмент кода, который я сузил, чтобы вызвать утечку памяти (то есть в диспетчере задач частный рабочий набор памяти увеличивается с той же повторяющейся строкой ввода). Я понимаю концепции куч и стеков памяти, а также общие правила, как избежать утечек памяти, но что-то где-то все еще идет не так:

while(!quit){
   char* thebuffer = new char[210]; 
   //checked the function, it isn't creating the leak
   int size = FuncToObtainInputTextFromApp(thebuffer); //stored in thebuffer
   string bufferstring = thebuffer;
   int startlog = bufferstring.find("$");
   int endlog = bufferstring.find("&");
   string str_text="";
   str_text = bufferstring.substr(startlog,endlog-startlog+1);
   String^ str_text_m = gcnew String(str_text_m.c_str());
   //some work done
   delete str_text_m;
   delete [] thebuffer; 
}

Единственное, о чем я могу подумать, так это о том, что это может быть создание 'строки str_text', поскольку она никогда не выходит за рамки видимости, поскольку в это время она просто перезапускается? Если так, то как бы я решил это? Определение его вне цикла while не решит проблему, так как оно также останется в области видимости. Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

4 голосов
/ 17 июня 2010

Вы должны использовать управление ресурсами с привязкой к области (также известное как RAII), это хорошая практика в любом случае.Никогда не выделяйте память вручную, храните ее в автоматически выделенном классе, который очистит ресурс для вас в деструкторе.

Ваш код может выглядеть следующим образом:

while(!quit)
{
    // completely safe, no leaks possible
    std::vector<char> thebuffer(210);
    int size = FuncToObtainInputTextFromApp(&thebuffer[0]);

    // you never used size, this should be better
    string bufferstring(thebuffer, size);

    // find does not return an int, but a size_t
    std::size_t startlog = bufferstring.find("$");
    std::size_t endlog = bufferstring.find("&");

    // why was this split across two lines?
    // there's also no checks to ensure the above find
    // calls worked, be careful
    string str_text = bufferstring.substr(startlog, endlog - startlog + 1);

    // why copy the string into a String? why not construct 
    // this directly?
    String^ str_text_m = gcnew String(str_text_m.c_str());

    // ...

    // don't really need to do that, I think,
    // it's garbage collected for a reason
    // delete str_text_m; 
}

Дело в том, что вы выигралиутечки памяти, если вы уверены, что ваши ресурсы освобождены сами по себе.Возможно, сборщик мусора вызывает сбои в работе вашего детектора утечек.

Кстати, в вашем коде слишком много ненужного копирования, вам может понадобиться переосмыслить, сколько раз вы копируете строку.(Например, найдите "$" и "&", пока он находится в векторе, и просто скопируйте оттуда в str_text, нет необходимости в промежуточной копии.)

2 голосов
/ 17 июня 2010

Вы #using std, так что тип str_text является std :: string?Может быть, вы хотели написать -

String^ str_text_m = gcnew String(str_text.c_str());

(а не gcnew String (str_text_m.c_str ()))?

Самое главное, выделение строки (или любого объекта) с помощью gcnew - это объявлениечто вы будете не удалять его явно - вы оставляете это на сборщик мусора.Не уверен, что произойдет, если вы действительно удалите его (технически это даже не указатель. Определенно не ссылается на что-либо в куче CRT, где new / delete имеют силу).

Вы можете смело комментировать удаление str_text_m.Вы можете ожидать постепенного увеличения памяти (там, где накапливается gcnew) и внезапного уменьшения (там, где начинается сборка мусора) через некоторые интервалы.

Еще лучше, вы, вероятно, можете повторно использовать str_text_m в соответствии с -

    String^ str_text_m = gcnew String();
    while(!quit){
       ...
       str_text_m = String(str_text.c_str());
       ...
    }
1 голос
/ 17 июня 2010

Я знаю, что рекомендуется устанавливать для освобожденной переменной значение NULL после ее удаления, чтобы предотвратить любую недопустимую ссылку на память.Может помочь, не может.

delete [] thebuffer; 
thebuffer = NULL;     // Clear a to prevent using invalid memory reference
0 голосов
/ 17 июня 2010

Существует инструмент под названием DevPartner, который может улавливать все утечки памяти во время выполнения. Если у вас есть pdb для вашего приложения, это даст вам номера строк в вашем приложении, где наблюдалась вся утечка памяти.

Лучше всего использовать для действительно больших приложений.

...