Вы искали инструменты для обнаружения утечек памяти, такие как Valgrind ?( Windows заменяет )
Выполнение этих команд в вашем коде покажет вам, сколько памяти у вас просачивается и, возможно, куда.
Это не полная программа,поэтому мы не можем передать это для вас.Несколько советов:
- Разбейте подпрограммы и создайте отдельные тестовые исполняемые файлы, чтобы убедиться, что в битах кода нет утечек памяти.Это похоже на разработку через тестирование - вы пишете тест для функции, чтобы убедиться, что она работает и правильно проверяет ввод, и вы также тестируете его на утечки памяти.
- Разработка в библиотеке, подобной моде.Это должно быть второй натурой, так как оно оптимизирует повторное использование кода (не повторяйте себя, если повторение не является выгодным) и помогает с вышеизложенным.
Редактировать: Я более подробно остановлюсь на этом.Чтобы дать вам представление о том, когда происходит утечка памяти, рассмотрите следующее:
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int* arr = new int(5);
// delete arr; // <-- uncomment this to fix memalloc bug.
return 0;
}
Эта программа очень просто выделяет 4 байта в куче, а затем завершает свою работу без очистки этой памяти.
Valgrindскажу вам:
HEAP SUMMARY:
==23008== in use at exit: 4 bytes in 1 blocks
==23008== total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==23008==
==23008== LEAK SUMMARY:
==23008== definitely lost: 4 bytes in 1 blocks
==23008== indirectly lost: 0 bytes in 0 blocks
==23008== possibly lost: 0 bytes in 0 blocks
==23008== still reachable: 0 bytes in 0 blocks
==23008== suppressed: 0 bytes in 0 blocks
Почему?Потому что у вас нет delete
d памяти, выделенной вам new
.Грубо говоря, это настолько сложно, насколько это возможно.
Я говорю, что это сложно, потому что программы довольно быстро становятся большими базами кода, а утечки памяти внезапно усложняются.Кто выделил память?Кто освободил это?Была ли выделена память как часть библиотеки?Что происходит, когда вы начинаете использовать массивы?Вы можете вызвать косвенную потерю памяти, освободив внешний уровень массива, но не внутренний.См. косвенная потеря памяти .
Это быстро становится очень сложным, особенно когда функции начинают выделять память, и вы начинаете использовать их в другом месте, и вы начинаете полагаться на программно определенные размеры памяти, такие как длиныстроки на основе пользовательского ввода.Ошибка maxlen+1
является распространенной ошибкой и может привести к огромным утечкам в больших двумерных массивах данных.
Редактировать 2 на основе вашего нового вопроса:
Во-первых, если вы используете C ++,Я настоятельно рекомендую забыть о malloc
.Используйте new
и delete
, потому что они понимают полиморфизм и объекты, а malloc
- нет.Ваши конструкторы могут быть вызваны неправильно.А если вам нужны строки, используйте тип string
.Если вам нужны массивы, обычно подойдет vector
.
Во-вторых, вы освобождаете память, только если операция чтения работает правильно.Зачем?Вы все еще распределили память, поэтому вам все еще нужно освободить ее, независимо от того, сработала ли операция чтения.Вы также должны проверить, что память действительно была выделена, в противном случае вы получите ошибку сегментации, вызванную доступом к памяти, к которой у вас нет доступа.
Отредактируйте три:
Хорошо, на основеваши комментарии, рассмотрите этот код, который, как я думаю, вы предлагаете:
char* buffer = (char*)malloc(4096*sizeof(char));
if ( ReadToSerialPort(buffer, ...) > 0 ) // you are proposing to free in this func call
{
// do stuff A
}
// do stuff B
// free(buffer); // <-- you should free buffer here
Что произойдет, если вы освободитесь внутри вызова функции?Ну, на самом деле это нормально, кроме того, что в области действия этого кода есть переменная, которую вы можете случайно использовать.Если вы это сделаете, вы получите доступ к памяти, которую вы явно освободили, что, вероятно, приведет к сбою вашей программы.
Я предполагаю, что на каком-то этапе вы захотите использовать этот буфер в части A или B.в этом случае вам нужно, чтобы эта память еще была выделена.
Что касается только освобождения внутри оператора if, это гарантированная утечка памяти, если функция чтения не работает, потому что эта память никогда не освобождается.
Вот как вы должны это сделать:
//
// I maintain you should use a string here, or
// if you insist on char*, use new.
// and delete.
//
char* buffer = (char*)malloc(4096*sizeof(char));
if ( buffer == NULL )
{
// os refused the alloc.
cout << "Out of memory\n" << endl;
return 1;
}
if ( ReadToSerialPort(buffer, ...) > 0 ) // this call frees as well?
{
// do stuff A using buffer
}
// do stuff B using buffer
free(buffer); // <-- you should free buffer here
Редактировать 4: Просто для пояснения:
Не смешивать malloc / free и new / delete . Если вы используете malloc, освободите эту память, если вы новичок, удалите эту память. Если вы взаимодействуете с кодом C, если для него не требуется массив типа int, вы можете использовать тип string
, и нет необходимости в динамическом размещении. Если вы не переходите к функции C, которой не управляете, вам, вероятно, следует рассмотреть vector
над массивом. Только если вы переходите к функции C, которую вы не можете контролировать, вам нужно войти в мир malloc и свободных методов C.