Why does Valgrind detect a memory leak in a calloc expression

I am trying to learn a couple things (like a hobby) and trying to learn how to use Valgrind. However, this does not make sense to me. Valgrind seems to say that bytes are lost when I allocate their calloc before I even use anything! Can someone explain what is happening here and why did the second program work? I compiled the programs in debug mode in Eclipse and ran Valgrind in the debug executable.

Here is the program:

1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <string.h> 4 5 int main(void) { 6 7 char* origstr = calloc(37, sizeof(char*)); 8 char* newsubstr = calloc(9, sizeof(char*)); 9 10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog"; 11 12 strncpy(newsubstr, origstr + 8, 8); 13 printf("SubString is: %s\n", newsubstr); 14 15 free(newsubstr); 16 free(origstr); 17 return 0; 18 } 

And here is what Walgrind gives me:

 $ valgrind --tool=memcheck --leak-check=full ./test ==25404== Memcheck, a memory error detector ==25404== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==25404== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info ==25404== Command: ./test ==25404== SubString is: BrownFox ==25404== Invalid free() / delete / delete[] / realloc() ==25404== at 0x4C29E90: free (vg_replace_malloc.c:473) ==25404== by 0x400665: main (test.c:16) ==25404== Address 0x4006f8 is not stack'd, malloc'd or (recently) free'd ==25404== ==25404== ==25404== HEAP SUMMARY: ==25404== in use at exit: 296 bytes in 1 blocks ==25404== total heap usage: 2 allocs, 2 frees, 368 bytes allocated ==25404== ==25404== 296 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==25404== at 0x4C2AD10: calloc (vg_replace_malloc.c:623) ==25404== by 0x4005FC: main (test.c:7) ==25404== ==25404== LEAK SUMMARY: ==25404== definitely lost: 296 bytes in 1 blocks ==25404== indirectly lost: 0 bytes in 0 blocks ==25404== possibly lost: 0 bytes in 0 blocks ==25404== still reachable: 0 bytes in 0 blocks ==25404== suppressed: 0 bytes in 0 blocks ==25404== ==25404== For counts of detected and suppressed errors, rerun with: -v ==25404== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 

If I remove the two free () statements, this is what Valgrind gives me:

 $ valgrind --tool=memcheck --leak-check=full ./test ==25597== Memcheck, a memory error detector ==25597== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==25597== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info ==25597== Command: ./test ==25597== SubString is: BrownFox ==25597== ==25597== HEAP SUMMARY: ==25597== in use at exit: 368 bytes in 2 blocks ==25597== total heap usage: 2 allocs, 0 frees, 368 bytes allocated ==25597== ==25597== 72 bytes in 1 blocks are definitely lost in loss record 1 of 2 ==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623) ==25597== by 0x4005BF: main (test.c:8) ==25597== ==25597== 296 bytes in 1 blocks are definitely lost in loss record 2 of 2 ==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623) ==25597== by 0x4005AC: main (test.c:7) ==25597== ==25597== LEAK SUMMARY: ==25597== definitely lost: 368 bytes in 2 blocks ==25597== indirectly lost: 0 bytes in 0 blocks ==25597== possibly lost: 0 bytes in 0 blocks ==25597== still reachable: 0 bytes in 0 blocks ==25597== suppressed: 0 bytes in 0 blocks ==25597== ==25597== For counts of detected and suppressed errors, rerun with: -v ==25597== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 

Now, if I run this program:

 1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <string.h> 4 5 int main(void) { 6 7 char* origstr; 8 char* newsubstr = calloc(9, sizeof(char*)); 9 10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog"; 11 12 strncpy(newsubstr, origstr + 8, 8); 13 printf("SubString is: %s\n", newsubstr); 14 15 free(newsubstr); 16 17 return 0; 18 } 

This shows that everything is fine:

 $ valgrind --tool=memcheck --leak-check=full ./test ==25862== Memcheck, a memory error detector ==25862== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==25862== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info ==25862== Command: ./test ==25862== SubString is: BrownFox ==25862== ==25862== HEAP SUMMARY: ==25862== in use at exit: 0 bytes in 0 blocks ==25862== total heap usage: 1 allocs, 1 frees, 72 bytes allocated ==25862== ==25862== All heap blocks were freed -- no leaks are possible ==25862== ==25862== For counts of detected and suppressed errors, rerun with: -v ==25862== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 

Why can't I calloc (highlight) origstr and then give it something? What if I would like to isolate this variable and during the program give it part of what is in another string variable, or use it to capture the result of another function that returns a string? Should I then handle this as if I did newsubstr?

This is a bit confusing to me, so can someone explain how this works so that I can better understand?

+5
source share
3 answers
 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog"; 

By doing this, you go to what origstr points origstr . Thereafter origstr does not indicate a block of memory allocated calloc .

And you free memory is not allocated by calloc or similar functions, which causes an error in your program.

Use strcpy to copy string to origstr -

 strcpy(origstr,"TheQuickBrownFoxJumpedOverTheLazyDog"); 

and then you can free origstr pointer.

+7
source

By assigning the string literal origstr , you will not copy the string, but simply change the value of origstr , thereby losing the pointer to calloc . free ing origstr now causes undefined behavior.

Use strcpy or strncpy instead to really save the string on the heap. But the actual calloc drop for origstr should be sufficient.


Notes:

  • like @LeeDanielCrocker mentioned in the comments on this answer, you probably intended to allocate space for char s, not char* s, drastically reducing the size of the allocated memory. You should replace sizeof(char*) with sizeof(char) ( aka 1 ).
+4
source

Because there is a memory leak. You reassign the pointer it is actually incorrect to free() , as it is.

To copy content to a highlighted pointer, use strcpy()

 strcpy(origstr, "TheQuickBrownFoxJumpedOverTheLazyDog"); 

Let's see how:

  • You are requesting memory using calloc()

     origstring = calloc(9, sizeof(char*)) 

    This is not true for several reasons.

    • You allocate space for 9 pointers, not 9 characters.
    • You really don't need calloc() , because you will immediately overwrite the contents, use malloc() .
  • You overwrite the pointer with a string literal

     origstr = "TheQuickBrownFoxJumpedOverTheLazyDog"; 

    now you have lost the reference to the pointer returned earlier by calloc() , and you cannot free() it, you should only return free() pointers to malloc()/calloc()/realloc() .

In truth, you do not need calloc() oristring pointer, calloc() / malloc() not to use so that you can assign to the pointer, but write to the memory pointed to by the pointer or, better, point to some memory that you can read / write from / to.

+2
source

Source: https://habr.com/ru/post/1232987/


All Articles