Следующая утечка:
static void memeat(void)
{
static char *foo = NULL;
foo = malloc(1024);
return;
}
Valgrind выход:
==16167== LEAK SUMMARY:
==16167== definitely lost: 4,096 bytes in 4 blocks
==16167== indirectly lost: 0 bytes in 0 blocks
==16167== possibly lost: 0 bytes in 0 blocks
==16167== still reachable: 1,024 bytes in 1 blocks
==16167== suppressed: 0 bytes in 0 blocks
==16167== Rerun with --leak-check=full to see details of leaked memory
Примечание. still reachable
(1024 байта) - это результат последнего ввода memeat()
. Статический указатель все еще содержал действительную ссылку на последний блок memeat()
, выделенный при выходе из программы. Только не предыдущие блоки.
Следующее НЕ утечка:
static void memeat(void)
{
static char *foo = NULL;
foo = realloc(foo, 1024);
return;
}
Выход Valgrind:
==16244== LEAK SUMMARY:
==16244== definitely lost: 0 bytes in 0 blocks
==16244== indirectly lost: 0 bytes in 0 blocks
==16244== possibly lost: 0 bytes in 0 blocks
==16244== still reachable: 1,024 bytes in 1 blocks
==16244== suppressed: 0 bytes in 0 blocks
==16244== Rerun with --leak-check=full to see details of leaked memory
Здесь адрес foo
, на который указывает указатель, был освобожден, а foo
теперь указывает на вновь выделенный адрес и будет продолжать делать это при следующем вводе memeat()
.
Пояснение:
Тип хранения static
говорит о том, что указатель foo
будет указывать на тот же адрес, что и инициализированный, каждый раз при входе в функцию. Однако, если вы меняете этот адрес каждый раз, когда функция вводится с помощью malloc()
или calloc()
, вы теряете ссылку на блоки из предыдущего распределения. Отсюда и утечка, поскольку любой из них собирается вернуть новый адрес.
«Все еще достижимо» в valgrind означает, что все выделенные блоки кучи все еще имеют действительный указатель для доступа / манипулирования / освобождения их при выходе. Это похоже на выделение памяти в main()
и не освобождение ее, а просто использование ОС для восстановления памяти.
Короче говоря, да - у вас есть утечка. Тем не менее, вы можете исправить это довольно легко. Просто отметьте, что вы действительно полагаетесь на свою ОС для восстановления памяти, если только вы не добавите в свою функцию еще один аргумент, который просто скажет ToHexString
вызвать free для статического указателя, который вы могли бы использовать при выходе.
Аналогично этому: (полная программа тестирования)
#include <stdlib.h>
static void memeat(unsigned int dofree)
{
static char *foo = NULL;
if (dofree == 1 && foo != NULL) {
free(foo);
return;
}
foo = realloc(foo, 1024);
return;
}
int main(void)
{
unsigned int i;
for (i = 0; i < 5; i ++)
memeat(0);
memeat(1);
return 0;
}
Выход Valgrind:
==16285== HEAP SUMMARY:
==16285== in use at exit: 0 bytes in 0 blocks
==16285== total heap usage: 6 allocs, 6 frees, 6,144 bytes allocated
==16285==
==16285== All heap blocks were freed -- no leaks are possible
Примечание к окончательному выводу :
Да, 6144 байта фактически были выделены в соответствии с тем, что malloc()
вернулось во время выполнения программы, но это просто означает, что статический указатель был освобожден, а затем перераспределен в соответствии с количеством введенных memeat()
. Фактическое использование кучи программы в любой момент времени было фактически всего 2 * 1024, 1k для выделения нового указателя, в то время как старый еще существовал, ожидая копирования в новый.
Опять же, не должно быть слишком сложно настроить ваш код, но мне не ясно, почему вы используете статическое хранилище для начала.