Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Valgrind definitely lost and reachable with exit vs main return

Tags:

c

valgrind

Valgrind reports definitely lost memory if I exit main with return 0;, but reports still reachable memory if I exit main with exit(0);.

test-reachable.c:

#include <stdlib.h>

int main() {
  void *data = malloc(256);
  exit(0);
}

test-lost.c:

#include <stdlib.h>

int main() {
  void *data = malloc(256);
  return 0;
}

Behavior:

$ gcc test-reachable.c -o test-reachable
$ valgrind --leak-check=yes ./test-reachable
==7696== Memcheck, a memory error detector
==7696== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7696== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7696== Command: ./test-reachable
==7696== 
==7696== 
==7696== HEAP SUMMARY:
==7696==     in use at exit: 256 bytes in 1 blocks
==7696==   total heap usage: 1 allocs, 0 frees, 256 bytes allocated
==7696== 
==7696== LEAK SUMMARY:
==7696==    definitely lost: 0 bytes in 0 blocks
==7696==    indirectly lost: 0 bytes in 0 blocks
==7696==      possibly lost: 0 bytes in 0 blocks
==7696==    still reachable: 256 bytes in 1 blocks
==7696==         suppressed: 0 bytes in 0 blocks
==7696== Reachable blocks (those to which a pointer was found) are not shown.
==7696== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==7696== 
==7696== For counts of detected and suppressed errors, rerun with: -v
==7696== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$ gcc test-lost.c -o test-lost
$ valgrind --leak-check=yes ./test-lost
==7774== Memcheck, a memory error detector
==7774== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7774== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7774== Command: ./test-lost
==7774== 
==7774== 
==7774== HEAP SUMMARY:
==7774==     in use at exit: 256 bytes in 1 blocks
==7774==   total heap usage: 1 allocs, 0 frees, 256 bytes allocated
==7774== 
==7774== 256 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7774==    at 0x4C2C080: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7774==    by 0x40051C: main (in /tmp/test-lost)
==7774== 
==7774== LEAK SUMMARY:
==7774==    definitely lost: 256 bytes in 1 blocks
==7774==    indirectly lost: 0 bytes in 0 blocks
==7774==      possibly lost: 0 bytes in 0 blocks
==7774==    still reachable: 0 bytes in 0 blocks
==7774==         suppressed: 0 bytes in 0 blocks
==7774== 
==7774== For counts of detected and suppressed errors, rerun with: -v
==7774== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Shouldn't these behave the same?

like image 953
skeggse Avatar asked Jul 25 '15 03:07

skeggse


2 Answers

Shouldn't these behave the same?

No.

In test-reachable.c the memory is referenced by the stack variable data at the time of the exit of the program, so it is still reachable, while in test-lost.c the memory is not referenced anymore because the main function has already returned, the reference does not exist anymore, the memory is definitely lost.

like image 170
4566976 Avatar answered Oct 24 '22 07:10

4566976


In C++ when return in main() is called then the destructors will be called for locally scoped objects whereas if exit() is called then no destructor will be called for locally scoped objects. I think this is similar in C with regards to objects allocated on the stack.

That probably explains why in the return case non freed memory is treated as definitely lost and in the exit(0) case the memory is reported as still reachable.

like image 2
doqtor Avatar answered Oct 24 '22 07:10

doqtor