Search code examples
cvalgrindfreecalloc

Valgrind insists there's still memory on the heap but I'm freeing the only pointer to the heap I have


I'm using Valgrind to find any memory leaks in my code, and according to the output there is 17 bytes that are still reachable, 1 alloc and 0 frees:

==9413== 
==9413== HEAP SUMMARY:
==9413==     in use at exit: 17 bytes in 1 blocks
==9413==   total heap usage: 1 allocs, 0 frees, 17 bytes allocated
==9413== 
==9413== 17 bytes in 1 blocks are still reachable in loss record 1 of 1
==9413==    at 0x402C109: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==9413==    by 0x80485F6: main (question3.c:21)
==9413== 
==9413== LEAK SUMMARY:
==9413==    definitely lost: 0 bytes in 0 blocks
==9413==    indirectly lost: 0 bytes in 0 blocks
==9413==      possibly lost: 0 bytes in 0 blocks
==9413==    still reachable: 17 bytes in 1 blocks
==9413==         suppressed: 0 bytes in 0 blocks
==9413== 
==9413== For counts of detected and suppressed errors, rerun with: -v
==9413== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

The thing is there is only one calloc in my code and I'm definitely freeing the pointer:

void checkInput(int err) {
  if (!err || err == EOF) {
    printf("\nInvalid input!\n");
    exit(1);
  }
}

#define N 17
int main() {
  char bufferStack[N] = { 'a' };
  char * bufferHeap = calloc(N, sizeof(char));
  char junk[N];
  printf("Enter a string no more than 16 chars long\n0123456789012345\n");
  checkInput(scanf("%16[^\n]", bufferStack));
  printf("BufferStack: %s\n", bufferStack);
  checkInput(scanf("%16[\n]", junk));
  checkInput(scanf("%16[^\n]", bufferHeap));
  printf("BufferHeap: %s\n", bufferHeap);
  free(bufferHeap);
  return 0;
}

I'm not sure where (or rather how) the memory is leaking. If anyone can help me find my bug or solve the problem I'd really appreciate it. Thanks.


Solution

  • If you enter more than 16 characters on the first prompt, the first call to scanf will pick up the first 16 characters, leaving any remaining characters in the input buffer.

    Then when the second scanf executes, it expects a newline character. The next character is not a newline but a character left over from the first prompt. This causes nothing to be matched, so scanf returns 0. This causes checkInput to print an error message and call exit, which immediately exits the program without freeing the memory. This is where the "still reachable" memory is coming from.

    You'll need to restructure your code so that all code paths free the allocated memory.