Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Definitely Lost Memory Leak in C Program

Would someone be able to shed light on why Valgrind classifies this program as a "Definitely Lost: 2 bytes in 1 block" memory leak? I understand that the commented line resolves the issue, but I don't understand the classification. According to Valgrind docs it appears that the memory leak should be classified as "Indirectly Reachable". I am also curious as to why this is even considered a memory leak and would appreciate an explanation. Is it good practice to manually free everything even though the program is terminating at the end of the main function?

#include <stdlib.h>

struct wrapper {
  char *data;
};

char *strdup(const char *);

struct wrapper *walloc(struct wrapper *root)
{
  if (root == NULL){
    root = (struct wrapper *) malloc(sizeof(struct wrapper));
    root->data = strdup("H");
  }

  return root;
}

int main(){
  struct wrapper *root;

  root = NULL;
  root = walloc(root);

  //free(root->data);

  return 0;
}

Here is the Valgrind output:

$ valgrind --leak-check=full ./leak
==26489== Memcheck, a memory error detector
==26489== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==26489== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==26489== Command: ./leak
==26489==
==26489==
==26489== HEAP SUMMARY:
==26489==     in use at exit: 2 bytes in 1 blocks
==26489==   total heap usage: 2 allocs, 1 frees, 1,790 bytes allocated
==26489==
==26489== 2 bytes in 1 blocks are definitely lost in loss record 1 of 1
==26489==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26489==    by 0x4EB79C9: strdup (in /usr/lib/libc-2.20.so)
==26489==    by 0x400542: walloc (leak.c:13)
==26489==    by 0x400542: main (leak.c:23)
==26489==
==26489== LEAK SUMMARY:
==26489==    definitely lost: 2 bytes in 1 blocks
==26489==    indirectly lost: 0 bytes in 0 blocks
==26489==      possibly lost: 0 bytes in 0 blocks
==26489==    still reachable: 0 bytes in 0 blocks
==26489==         suppressed: 0 bytes in 0 blocks
==26489==
==26489== For counts of detected and suppressed errors, rerun with: -v
==26489== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
like image 427
Pan Thomakos Avatar asked Sep 23 '14 06:09

Pan Thomakos


People also ask

What is memory leak in C++?

Memory leak occurs when we keep allocating memory in the heap without freeing it, i.e., the allocated memory in heap is not released back to the heap. The overall memory usage keeps on increasing and reduces the available memory for the program which results in reduction of efficiency or program performance.

How to check if a program has lost memory?

Try testing on ucpu1 or ucpu2 to double check. "definitely lost": your program is leaking memory, you have free () 'd a struct and forgotten to free the list values inside the struct and therefore the list cannot be reached anymore. "invalid write": the program wrote to some memory it should not have due to a heap block overrun.

What happens if a program has memory leaks?

If a program has memory leaks, then its memory usage is satirically increasing since all systems have limited amount of memory and memory is costly. Hence it will create problems. How to avoid Memory Leak?

What does it mean when a program says probably lost?

"probably lost": your program is leaking memory, you have not free () 'd some allocated memory or you have changed the pointer to the object and hence, lost the original pointer. If you see this on OSX, it may be a false positive. Try testing on ucpu1 or ucpu2 to double check.


2 Answers

strdup allocates memory on the heap (using malloc) and therefore you need to free this memory when it's no longer in use like for anyone of your own direct call to malloc.

You must do that even when the program finish because this is the only way to detect a memory leak. Of course, the notion of checking for any memory leak might seem a little overkill when a program finish because all of its allocated memory is then automatically released by the OS but don't forget that your small program is an exception here. Usually, most programs will take a very large amount of memory when running and might run out of memory or run much slower if there are multiple memory leaks inside them.

Even a small program should be well written; otherwise it will become impossible for you to write any big programs later because your bad habits will translate into a tons of coding errors.

like image 200
SylvainL Avatar answered Oct 08 '22 15:10

SylvainL


Thanks to @sharth for pointing me in the right direction. The Direct Loss was actually properly detected by Valgrind, but was confusing due to the -O3 compilation which removed root entirely. Compiling without -O3 shows the proper direct loss of 8 bytes and indirect loss of 2 bytes.

Also, thanks to @SylvainL and @Lundin for their best practices comments.

FYI: The corrected Valgrind output looks like this:

==30492== Memcheck, a memory error detector
==30492== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==30492== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==30492== Command: ./leak
==30492==
==30492==
==30492== HEAP SUMMARY:
==30492==     in use at exit: 10 bytes in 2 blocks
==30492==   total heap usage: 3 allocs, 1 frees, 1,830 bytes allocated
==30492==
==30492== 10 (8 direct, 2 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==30492==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30492==    by 0x400687: walloc (leak.c:12)
==30492==    by 0x4006C6: main (leak.c:23)
==30492==
==30492== LEAK SUMMARY:
==30492==    definitely lost: 8 bytes in 1 blocks
==30492==    indirectly lost: 2 bytes in 1 blocks
==30492==      possibly lost: 0 bytes in 0 blocks
==30492==    still reachable: 0 bytes in 0 blocks
==30492==         suppressed: 0 bytes in 0 blocks
==30492==
==30492== For counts of detected and suppressed errors, rerun with: -v
==30492== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
like image 30
Pan Thomakos Avatar answered Oct 08 '22 16:10

Pan Thomakos