3

I can't understand why valgrind (version 3.14) doesn't detect a possible memory leak in this program:

#include <stdlib.h>

int main() {
  int *p = malloc(sizeof(int));
  p = realloc(p, 2 * sizeof(int));

  free(p);

  return 0;
}

The C99 standard (ISO/IEC 9899:1999, page 314) says this about realloc:

If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged. [...] The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.

So it may occur that p is NULL but the memory cell previously allocated with malloc is still there, shouldn't this be a possible memory leak?

If I compile the program with gcc -std=c99 and I execute valgrind with --tool=memcheck --leak-check=full --track-origins=yes it gives the following message:

==313618== Memcheck, a memory error detector
==313618== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==313618== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==313618== Command: ./a.out
==313618== 
==313618== 
==313618== HEAP SUMMARY:
==313618==     in use at exit: 0 bytes in 0 blocks
==313618==   total heap usage: 2 allocs, 2 frees, 12 bytes allocated
==313618== 
==313618== All heap blocks were freed -- no leaks are possible
==313618== 
==313618== For counts of detected and suppressed errors, rerun with: -v
==313618== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
melpomene
  • 84,125
  • 8
  • 85
  • 148
Andrea Ciceri
  • 436
  • 6
  • 16
  • This is a good reason why you should assign the return value from `realloc` to a temporary variable to test before you overwrite the original pointer. Then if `NULL` was returned your recovery action can `free` the original pointer, instead of having lost it. – Weather Vane Oct 01 '19 at 18:00
  • 2
    More on what valgrind means by "possible" in this context: https://stackoverflow.com/questions/6771610/what-does-possible-lost-means-in-valgrind –  Oct 01 '19 at 18:04
  • @WeatherVane I knew that this use of realloc is wrong, the problem was why valgrind didn't detect it. – Andrea Ciceri Oct 02 '19 at 10:33
  • @JETM This is really useful, however "possible" is a misleading name, as well as the message "no leaks are possible"... – Andrea Ciceri Oct 02 '19 at 10:36

1 Answers1

9

Valgrind does not analyze your code; it analyzes the actions taken by your code.

In this particular run realloc did not fail, so there was no memory leak, so valgrind had nothing to report:

All heap blocks were freed

And that's all valgrind knows.

To detect the problem in your code you need a static code analysis tool.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • 1
    Yes, as you stated in answer by using `cppcheck` a static C/C++ code analyzer we can detect these problem. – EsmaeelE Oct 01 '19 at 22:53
  • On GNU/Linux `sudo apt install cppcheck` and `cppcheck source.c` produce: `9]: (error) Common realloc mistake: 'p' nulled but not freed upon failure` – EsmaeelE Oct 01 '19 at 22:54
  • Correct the original code: `int *p = malloc(sizeof(int)); int *tmp = NULL; tmp = realloc(p, 2 * sizeof(int)); if (tmp){ p=tmp; free(tmp); tmp=NULL; }else{ printf("error\n"); tmp=NULL; } free(p);` – EsmaeelE Oct 01 '19 at 22:58
  • @EsmaeelE Thank you, I tried using cppcheck and it correctly warns me. – Andrea Ciceri Oct 02 '19 at 10:31