Custom allocator: Valgrind shows 7 allocs, 0 frees, no leaks - c

I am working on a clone of the malloc (3) functions (malloc, realloc and free for now).
I would like to add support for Valgrind. I'm using these docs. However, after adding calls to the VALGRIND_MEMPOOL_FREE, VALGRIND_MEMPOOL_ALLOC and VALGRIND_CREATE_MEMPOOL macros, I get the following from Valgrind:
==22303== HEAP SUMMARY:
==22303== in use at exit: 0 bytes in 0 blocks
==22303== total heap usage: 7 allocs, 0 frees, 2,039 bytes allocated
==22303==
==22303== All heap blocks were freed -- no leaks are possible
This is despite my realloc calling VALGRIND_MEMPOOL_FREE and my free calling VALGRIND_MEMPOOL_FREE.
What could be the cause of this ?

What could be the cause of this ?
This is due to a bug in valgrind. See the link to the valgrind bug tracker in my comment to your answer.
From the other link in my comment:
A cursory search through the source code indicates that MEMPOOL_ALLOC
calls new_block, which increments cmalloc_n_mallocs, but there is no
corresponding change to cmalloc_n_frees in MEMPOOL_FREE.
/* valgrind.c */
#include <valgrind/valgrind.h>
int main(int argc, char *argv[]) {
char pool[100];
VALGRIND_CREATE_MEMPOOL(pool, 0, 0);
VALGRIND_MEMPOOL_ALLOC(pool, pool, 8);
VALGRIND_MEMPOOL_FREE(pool, pool);
VALGRIND_DESTROY_MEMPOOL(pool);
return 0;
}
$ gcc valgrind.c -g
$ valgrind --leak-check=full --show-leak-kinds=all ./a.out
==10186== Memcheck, a memory error detector
==10186== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==10186== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==10186== Command: ./a.out
==10186==
==10186==
==10186== HEAP SUMMARY:
==10186== in use at exit: 0 bytes in 0 blocks
==10186== total heap usage: 1 allocs, 0 frees, 8 bytes allocated
==10186==
==10186== All heap blocks were freed -- no leaks are possible
==10186==
==10186== For counts of detected and suppressed errors, rerun with: -v
==10186== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$

Taken from here: http://valgrind.10908.n7.nabble.com/VALGRIND-MEMPOOL-FREE-not-reflected-in-heap-summary-td42789.html
A cursory search through the source code indicates that MEMPOOL_ALLOC
calls new_block, which increments cmalloc_n_mallocs, but there is no
corresponding change to cmalloc_n_frees in MEMPOOL_FREE. Here's a
patch that increments it at the very end of MEMPOOL_FREE. This gives
me the behavior I expect.

Related

Why doesn't valgrind detect this possible memory leak due to realloc?

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)
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.

Why libcurl still leaves reachable blocks after cleanup calls?

I have been using libcurl to handle get/post requests and valgrind always shows me the same amount of reachable blocks (21). What I missing in the standard cURL's configuration to avoid that?
This is the simplest code with the "error":
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
int main(int argc, char const *argv[]) {
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
·
·
·
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
I compile with
$ gcc -o test cURL.c -lcurl
Valgrind check
$ valgrind --leak-check=full --track-origins=yes ./test
==4295== Memcheck, a memory error detector
==4295== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4295== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4295== Command: ./test
==4295==
==4295==
==4295== HEAP SUMMARY:
==4295== in use at exit: 858 bytes in 21 blocks
==4295== total heap usage: 4,265 allocs, 4,244 frees, 185,353 bytes allocated
==4295==
==4295== LEAK SUMMARY:
==4295== definitely lost: 0 bytes in 0 blocks
==4295== indirectly lost: 0 bytes in 0 blocks
==4295== possibly lost: 0 bytes in 0 blocks
==4295== still reachable: 858 bytes in 21 blocks
==4295== suppressed: 0 bytes in 0 blocks
==4295== Reachable blocks (those to which a pointer was found) are not shown.
==4295== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==4295==
==4295== For counts of detected and suppressed errors, rerun with: -v
==4295== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
libcurl links against many libraries, and some of them do not have a function like curl_global_cleanup which reverts initialization and frees all memory. This happens when libcurl is linked against NSS for TLS support, and also with libssh2 and its use of libgcrypt. GNUTLS as the TLS implementation is somewhat cleaner in this regard.
In general, this is not a problem because these secondary libraries are only used on operating systems where memory is freed on process termination, so an explicit cleanup is not needed (and would even slow down process termination). Only with certain memory debuggers, the effect of missing cleanup routines is visible, and valgrind deals with this situation by differentiating between actual leaks (memory to which no pointers are left) and memory which is still reachable at process termination (so that it could have been used again if the process had not terminated).

Why does Valgrind show a memory leak on a calloc statement

I'm trying to learn a couple things (just as a hobby) and trying to learn to use Valgrind. However this doesn't seem to make sense to me. It seems Valgrind is saying that bytes are lost when I'm allocating them with calloc before I even use anything! Can someone explain what is going on here and why the second program worked? I compiled the programs in debug mode in Eclipse and ran Valgrind on the debug executable.
Here's 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's what Valgrind 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, here's 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 }
It shows everything is just 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 is it that I can't calloc (allocate) origstr and then give it something? What if I wanted to allocate that variable and in the course of the program give it part of what's in another string variable or use it to capture the result of another function that returns a string? Would I then have to handle it like I did newsubstr?
This is a bit confusing to me so can someone explain how this works so I can understand it better?
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
By doing this you change to what origstr points to . After this origstr doesn't point to memory block allocated by calloc .
And you free memory not allocated by calloc or similar functions , thus causing error in your program.
Use strcpy to copy string to origstr -
strcpy(origstr,"TheQuickBrownFoxJumpedOverTheLazyDog");
and then you can free your pointer origstr.
By assigning the string literal to origstr you don't copy the string but just change origstrs value, thus losing the pointer to calloc. freeing origstr now causes undefined behavior.
Use strcpy or strncpy instead to really store the string on the heap. But actually dropping calloc for origstr should suffice.
Notes:
as #LeeDanielCrocker mentioned in the comments to this answer, you probably intended to allocate space for chars, not for char*s, decreasing the size of the allocated memory drastically. You should replace the sizeof(char*) with a sizeof(char) (a.k.a. 1).
Because there is a memory leak. You reassign the pointer, it's actually incorrect to free() it as you have it.
To copy the contents to the allocated pointer use strcpy()
strcpy(origstr, "TheQuickBrownFoxJumpedOverTheLazyDog");
Let's see how:
You request memory with calloc()
origstring = calloc(9, sizeof(char*))
this is wrong for multiple reasons
You are allocating space for 9 pointers, not 9 characters.
You don't really need calloc() because you will overwrite the contents immediately, use malloc().
You overwrite the pointer with a string literal
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
now you lost reference to the pointer returned earlier by calloc() and you cannot possible free() it, you should only free() pointers return by malloc()/calloc()/realloc().
The truth is, you don't need to calloc() the oristring pointer, calloc()/malloc() are not used to allow you to assign to a pointer, but to write to the memory pointed to by the pointer, or better, to point to some memory you can read/write from/to.

Don't see line numbers using Valgrind inside Ubuntu (Vagrant+Virtualbox)

I am currently reading and fallowing along the "Learn C The Hard Way"-book. On exercise 4 I have to install Valgrind. I first did this locally on my Macbook running Maverick, but I received a warning that Valgrind might not work 100%.
So now I tried it with Vagrant (using VirtualBox) with an Ubuntu 12.04 box. You can check out the exact Vagrantfile (setup) and the exercise files here on my github repo.
The problem:
I don't see the line numbers and instead I get something like 0x40052B.
I compiled the files by doing the fallowing:
$ make clean # Just to be sure
$ make
$ valgrind --track-origins=yes ./ex4
I pasted the result to pastebin here.
I found the fallowing 3 questions on SO that (partly) describes the same problem, but the answer's and there solutions didn't work for me:
Valgrind not showing line numbers in spite of -g flag (on Ubuntu 11.10/VirtualBox)
How do you get Valgrind to show line errors?
Valgrind does not show line-numbers
What I have tried sofar:
Added libc6-dbg
installed gcc and tried compiling with that instead of cc.
added --track-origins=yes to the valgrind-command
Added (and later removed) compiling with -static and -oO flags
So I am not sure where to go from here? I could try and install the latest (instead of v3.7) off gcc manually although that looked rather difficult.
edit:
#abligh answer seems to be right. I made this with kaleidoscope:
On the left side you see the result of: valgrind --track-origins=yes ./ex4 and on the right side the result of valgrind ./ex4.
I guess I still need to learn allot about c and it's tools.
I think you are just missing them in the output.
Here is some of your output (copied from Pastebin):
==16314== by 0x40052B: main (ex4.c:9)
^^--- LINE NUMBER
==16314== Uninitialised value was created by a stack allocation
==16314== at 0x4004F4: main (ex4.c:4)
^^--- LINE NUMBER
Though I think your invocation is wrong to check memory leaks. I wrote a very simple program to leak one item:
#include <stdio.h>
#include <stdlib.h>
int
main (int argc, char **argv)
{
void *leak;
leak = malloc (1);
printf ("Leaked %p\n", leak);
exit (0);
}
and compiled it using your Makefile:
gcc -Wall -g test.c -o test
Running your command:
$ valgrind --track-origins=yes ./test
==26506== Memcheck, a memory error detector
==26506== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==26506== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==26506== Command: ./test
==26506==
Leaked 0x51f2040
==26506==
==26506== HEAP SUMMARY:
==26506== in use at exit: 1 bytes in 1 blocks
==26506== total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==26506==
==26506== LEAK SUMMARY:
==26506== definitely lost: 0 bytes in 0 blocks
==26506== indirectly lost: 0 bytes in 0 blocks
==26506== possibly lost: 0 bytes in 0 blocks
==26506== still reachable: 1 bytes in 1 blocks
==26506== suppressed: 0 bytes in 0 blocks
==26506== Rerun with --leak-check=full to see details of leaked memory
==26506==
==26506== For counts of detected and suppressed errors, rerun with: -v
==26506== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
But invoking the way I normally invoke it:
$ valgrind --leak-check=full --show-reachable=yes ./test
==26524== Memcheck, a memory error detector
==26524== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==26524== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==26524== Command: ./test
==26524==
Leaked 0x51f2040
==26524==
==26524== HEAP SUMMARY:
==26524== in use at exit: 1 bytes in 1 blocks
==26524== total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==26524==
==26524== 1 bytes in 1 blocks are still reachable in loss record 1 of 1
==26524== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26524== by 0x40059C: main (test.c:8)
==26524==
==26524== LEAK SUMMARY:
==26524== definitely lost: 0 bytes in 0 blocks
==26524== indirectly lost: 0 bytes in 0 blocks
==26524== possibly lost: 0 bytes in 0 blocks
==26524== still reachable: 1 bytes in 1 blocks
==26524== suppressed: 0 bytes in 0 blocks
==26524==
==26524== For counts of detected and suppressed errors, rerun with: -v
==26524== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
Note the line numbers are again in brackets, e.g.
==26524== by 0x40059C: main (test.c:8)
^^^^^^^^ <- FILENAME AND LINE NUMBER

Just a loop, and 33 leaks

Look something strange on my mac :
$> cat main.c
#include <stdio.h>
int main(int ac, char **av) {
for (int i = 0; i < ac; i++)
printf("%s\n", av[i]);
return 0;
}
$> gcc main.c -std=c99
$> valgrind ./a.out hello my friends
And here is the result :
==725== Memcheck, a memory error detector
==725== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==725== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==725== Command: ./a.out hello my friends
==725==
--725-- ./a.out:
--725-- dSYM directory is missing; consider using --dsymutil=yes
./a.out
hello
my
friends
==725==
==725== HEAP SUMMARY:
==725== in use at exit: 6,146 bytes in 33 blocks
==725== total heap usage: 33 allocs, 0 frees, 6,146 bytes allocated
==725==
==725== LEAK SUMMARY:
==725== definitely lost: 0 bytes in 0 blocks
==725== indirectly lost: 0 bytes in 0 blocks
==725== possibly lost: 0 bytes in 0 blocks
==725== still reachable: 6,146 bytes in 33 blocks
==725== suppressed: 0 bytes in 0 blocks
==725== Rerun with --leak-check=full to see details of leaked memory
==725==
==725== For counts of detected and suppressed errors, rerun with: -v
==725== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
If someone knows why, and could explain me where does theses leaks come from, I'd be thankful !!
Have a good day :-)
These aren't leaks. Objects listed as still reachable shouldn't trouble you. If you'd have a non-zero value in the rows above then it should ring an alarm bell though!
Those 33 blocks listed as still reachable are most probably some blocks allocated inside printf calls by your standard library. Nothing to be worried about.
Consider also taking a look at this answer to a similar question.
"still reachable" when a program has terminated is really nothing to worry about.
"still reachable" means that there are allocated memory which hasn't been released, but there are still pointers pointing towards this memory. Therefor valgrind doesn't flag it as a true memory "leak".
It's often a waste of time to spend time free:ing the allocated memory before a application ends, the allocated memory will be returned to the OS anyhow since the application is terminating.

Resources