Я не могу добавить к тому, что говорили другие в отношении определения утечек памяти, но я могу дать вам несколько замечаний о том, когда могут произойти утечки памяти.
Первый случай, который приходит на ум - это функция, которая выполняет распределение:
int* somefunction(size_t sz)
{
int* mem;
mem = malloc(sz*sizeof(int));
return mem;
}
Нет ничего унаследованного в написании функции таким образом. Это очень похоже на malloc. Проблема в том, что вы сейчас начинаете делать:
int* x = somefunction(5);
И это легко забыть, теперь это не malloc, чтобы освободить x. Опять же, в этом нет ничего, что означало бы, что вы забудете , но мой опыт подсказывает мне, что я и другие это упускаем из виду.
Хорошей стратегией для решения этой проблемы является указание в названии функции, что происходит распределение. Итак, вызовите функцию somefunction_alloc
.
Второй случай, который приходит на ум, - это потоки, особенно fork()
, потому что весь код как бы в одном месте. Если вы аккуратно кодируете с помощью функций, нескольких файлов и т. Д., Вы почти всегда избегаете ошибок, но помните, что все должно быть свободно в некоторой области, включая то, что было выделено как post fork (), так и pre fork. Учтите это:
int main()
{
char* buffer = malloc(100*sizeof(char));
int fork_result = fork();
if ( fork_result < 0 )
{
printf("Error\n");
return 1;
}
elseif ( fork_result == 0 )
{
/* do child stuff */
return 0;
}
else
{
/* do parent stuff */
}
free(buffer);
return 0;
}
Здесь есть небольшая ошибка. Родитель не будет пропускать память, но child делает , потому что это точная копия родительского объекта, включая кучу, но она выходит перед освобождением чего-либо. Свободное должно происходить на обоих путях кода. Точно так же, если вилка не удалась, вы все равно не освободились. Легко пропустить вещи, когда вы пишете такой код. Лучший способ - создать переменную кода выхода, такую как int status = 0;
, и изменить ее при возникновении ошибок, а не использовать return в любой структуре , но разрешить пути дочернего и родительского кода продолжать до конца запрограммируйте как они должны.
Тем не менее, многопоточность и разветвление всегда затрудняют отладку из-за их природы.