What does Valgrind mean when it says memory is "definitely lost"? - c

The following program:
#include <stdlib.h>
int main(void)
{
char *my_str = malloc(42 * sizeof(char));
return 0;
}
Compiled as such:
gcc -g -o prog prog.c
And executed with Valgrind as such:
valgrind --leak-check=full ./prog
Produces the following (truncated) output:
...
==18424== HEAP SUMMARY:
==18424== in use at exit: 42 bytes in 1 blocks
==18424== total heap usage: 1 allocs, 0 frees, 42 bytes allocated
==18424==
==18424== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==18424== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18424== by 0x10865B: main (main.c:5)
==18424==
==18424== LEAK SUMMARY:
==18424== definitely lost: 42 bytes in 1 blocks
==18424== indirectly lost: 0 bytes in 0 blocks
==18424== possibly lost: 0 bytes in 0 blocks
==18424== still reachable: 0 bytes in 0 blocks
==18424== suppressed: 0 bytes in 0 blocks
...
Why does Valgrind say that the unfreed memory is "definitely lost"?
From the Valgrind Memcheck docs:
This means that no pointer to the block can be found. The block is classified as "lost", because the programmer could not possibly have freed it at program exit, since no pointer to it exists. This is likely a symptom of having lost the pointer at some earlier point in the program.
However, it's pretty clear that I could have easily freed the block before program exit. What am I missing here? Shouldn't the memory be "still reachable"?

Here's an example of "definitely lost" vs. "still reachable":
#include <stdio.h>
#include <stdlib.h>
void *p;
int main()
{
p = malloc(10);
p = malloc(100);
void *m = malloc(50);
return 0;
}
What happens in this code is the following:
10 bytes are allocated and the pointer to this memory is assigned to the global p.
100 bytes are allocated and the pointer to this memory is assigned to the global p. This overwrites the pointer value that pointed to 10 allocated bytes, and there is no other reference to it. So that memory is "definitely lost".
50 bytes are allocated and the pointer to this memory is assigned to the local m.
main returns causing the lifetime of m to end. As a result there is no reference stored to the memory pointer to 50 bytes so that memory is "definitely lost".
The pointer value pointing to 100 bytes still lives in the global p, so cleanup routines such as those called by atexit or other compiler specific methods could still clean up that memory. So it is "still reachable".
When running valgrind on this code, it outputs the following:
==60822== Memcheck, a memory error detector
==60822== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==60822== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==60822== Command: ./x1
==60822==
==60822==
==60822== HEAP SUMMARY:
==60822== in use at exit: 160 bytes in 3 blocks
==60822== total heap usage: 3 allocs, 0 frees, 160 bytes allocated
==60822==
==60822== LEAK SUMMARY:
==60822== definitely lost: 60 bytes in 2 blocks
==60822== indirectly lost: 0 bytes in 0 blocks
==60822== possibly lost: 0 bytes in 0 blocks
==60822== still reachable: 100 bytes in 1 blocks
==60822== suppressed: 0 bytes in 0 blocks
==60822== Rerun with --leak-check=full to see details of leaked memory
==60822==
==60822== For counts of detected and suppressed errors, rerun with: -v
==60822== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Which is consistent with the description above.
So to summarize, memory is "still reachable" if a pointer to it is stored either in a file scope variable or is pointed to by any "still reachable" memory. Otherwise it is lost.

Why does Valgrind say that the unfreed memory is "definitely lost"?
Because - once main returns the variable my_str doesn't exist anymore. Consequently, there is no way to free the allocated memory. And there is no way to reach the memory. No one know where the memory is. It's lost.
Note: All modern OS systems will however take care of the memory clean up so it's not a real problem.

Valgrind is checking for memory leaks, and you are leaking memory as you didn't free the pointer before exit. You should free(my_str) .
int main(void)
{
char *my_str = malloc(42 * sizeof(char));
free (my_str);
return 0;
}
Definitely Lost mean that nobody has a reference to that memory location anymore, so nobody could free that memory. In a context of a running program that will be a segment of memory that nobody could reuse (so it is lost). Of course at the end of the program nobody will ever use it again, but some of the memory could be referenced by another leaking object (and will be an indirect lost), so with those hints you can debug your program. The link bellow shows a discussion on the topic.
This is a complete response on why you should free memory before exit

Related

How to let valgrind to report "where" a "definitely lost" happens

Is there a way to let valgrind to report "where" a "definitely lost" happens?
What I want is not "where it's allocated", but "where that poor piece of memory got leaked".
For example, this piece of code has a "definitely lost" leak when f() returns:
#include <stdlib.h>
void f () {
void *ptr = malloc(42);
}
int main () {
f();
return 0;
}
But valgrind only reports the origin of allocation:
==9772== HEAP SUMMARY:
==9772== in use at exit: 42 bytes in 1 blocks
==9772== total heap usage: 1 allocs, 0 frees, 42 bytes allocated
==9772==
==9772== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==9772== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9772== by 0x40053E: f (test.c:4)
==9772== by 0x400552: main (test.c:8)
==9772==
==9772== LEAK SUMMARY:
==9772== definitely lost: 42 bytes in 1 blocks
==9772== indirectly lost: 0 bytes in 0 blocks
==9772== possibly lost: 0 bytes in 0 blocks
==9772== still reachable: 0 bytes in 0 blocks
==9772== suppressed: 0 bytes in 0 blocks
==9772==
==9772== For counts of detected and suppressed errors, rerun with: -v
==9772== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I'm using --leak-check=full and --track-origins=yes.
What I want is not "where it's allocated", but "where that poor piece
of memory got leaked".
No, Valgrind only reports where the memory was allocated, but not when how or why it was leaked. This behavior is documented in Memcheck manual:
If --leak-check=full is specified, Memcheck will give details for each
definitely lost or possibly lost block, including where it was
allocated. (Actually, it merges results for all blocks that have the
same leak kind and sufficiently similar stack traces into a single
"loss record". The --leak-resolution lets you control the meaning of
"sufficiently similar".) It cannot tell you when or how or why the
pointer to a leaked block was lost; you have to work that out for
yourself.
Also --track-origins has nothing to do with memory leaks. It is used for tracking the origin of uninitialised values.

Understand memory leak types in valgrind memcheck tool

I am using Valgrind tool to understand the different types of memory leaks:
Directly lost,Indirectly lost Still reachable and possibly lost.
Ex1:
#include<stdio.h>
#include <stdlib.h>
main() {
int *p, i;
p = malloc(10*sizeof(int));
for(i = 0;i < 10;i++)
p[i] = i;
//free(p);
printf("Freed\n ");
}
LEAK SUMMARY:
==31770== definitely lost: 0 bytes in 0 blocks
==31770== indirectly lost: 0 bytes in 0 blocks
==31770== possibly lost: 20 bytes in 1 blocks
==31770== still reachable: 0 bytes in 0 blocks
==31770== suppressed: 0 bytes in 0 blocks
eg2:
main() {
int *p, i;
p = malloc(10*sizeof(int));
// printf("freed");
}
LEAK SUMMARY:
==14950== definitely lost: 0 bytes in 0 blocks
==14950== indirectly lost: 0 bytes in 0 blocks
==14950== possibly lost: 0 bytes in 0 blocks
==14950== still reachable: 40 bytes in 1 blocks
==14950== suppressed: 0 bytes in 0 blocks
If a uncomment the printf statement:
LEAK SUMMARY:
==15889== definitely lost: 40 bytes in 1 blocks
==15889== indirectly lost: 0 bytes in 0 blocks
==15889== possibly lost: 0 bytes in 0 blocks
==15889== still reachable: 0 bytes in 0 blocks
==15889== suppressed: 0 bytes in 0 blocks
Please explain me exactly about those different memory leaks.
A quick internet search leads to the following site:
http://valgrind.org/docs/manual/faq.html#faq.deflost
The details are in the Memcheck section of the user manual.
In short:
"definitely lost" means your program is leaking memory -- fix
those leaks!
"indirectly lost" means your program is leaking memory in a
pointer-based structure. (E.g. if the root node of a binary tree is
"definitely lost", all the children will be "indirectly lost".) If you
fix the "definitely lost" leaks, the "indirectly lost" leaks should go
away.
"possibly lost" means your program is leaking memory, unless
you're doing unusual things with pointers that could cause them to
point into the middle of an allocated block; see the user manual for
some possible causes. Use --show-possibly-lost=no if you don't want to
see these reports.
"still reachable" means your program is probably ok -- it didn't
free some memory it could have. This is quite common and often
reasonable. Don't use --show-reachable=yes if you don't want to see
these reports.
"suppressed" means that a leak error has been suppressed. There
are some suppressions in the default suppression files. You can ignore
suppressed errors.
Update:
The difference between "definitely lost" and "still reachable" is as follows:
Your memory is definitely lost if all references to it are gone and you did not free it before - the classical case of a memory leak.
It is still reachable when, at the end of your program's lifetime, you did not free all memory that was dynamically allocated but there are still valid references to it, so that it could have been freed.
Since all of the program's memory is freed at program termination anyway, this isn't usually a problem. However for a long running program and large memory allocations, it might be worth manually freeing those if you don't need them anymore.
Let me show you a simple example:
#include <stdio.h>
#include <stdlib.h>
char *still_reachable;
char *definitely_lost_global;
int main()
{
char *definitely_lost_local;
// allocate 10 bytes of memory -> will get lost
definitely_lost_local = malloc(10 * sizeof *definitely_lost_local);
// allocate 20 bytes of memory -> will get lost
definitely_lost_global = malloc(20 * sizeof *definitely_lost_global);
definitely_lost_global = NULL;
// Now there aren't any references to those 20 bytes anymore, so memory is lost.
// allocate 40 bytes of memory. The global pointer has static storage duration.
// We do not change the pointer, so the respective memory will
// be still reachable by the end of program lifetime
still_reachable = malloc(40 * sizeof *still_reachable);
} // scope of definitely_lost_local ends here --> 10 bytes are lost!
We can guess that 10+20 = 30 bytes will be lost in this example, while 40 bytes will be still reachable. So let's check with valgrind:
==19474== Memcheck, a memory error detector
==19474== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==19474== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==19474== Command: ./prog
==19474==
==19474==
==19474== HEAP SUMMARY:
==19474== in use at exit: 70 bytes in 3 blocks
==19474== total heap usage: 3 allocs, 0 frees, 70 bytes allocated
==19474==
==19474== LEAK SUMMARY:
==19474== definitely lost: 30 bytes in 2 blocks
==19474== indirectly lost: 0 bytes in 0 blocks
==19474== possibly lost: 0 bytes in 0 blocks
==19474== still reachable: 40 bytes in 1 blocks
==19474== suppressed: 0 bytes in 0 blocks
==19474== Rerun with --leak-check=full to see details of leaked memory
==19474==
==19474== For counts of detected and suppressed errors, rerun with: -v
==19474== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Voilá, as expected.

Definitely Lost Memory Leak in C Program

Would someone be able to shed light on why Valgrind classifies this program as a "Definitely Lost: 2 bytes in 1 block" memory leak? I understand that the commented line resolves the issue, but I don't understand the classification. According to Valgrind docs it appears that the memory leak should be classified as "Indirectly Reachable". I am also curious as to why this is even considered a memory leak and would appreciate an explanation. Is it good practice to manually free everything even though the program is terminating at the end of the main function?
#include <stdlib.h>
struct wrapper {
char *data;
};
char *strdup(const char *);
struct wrapper *walloc(struct wrapper *root)
{
if (root == NULL){
root = (struct wrapper *) malloc(sizeof(struct wrapper));
root->data = strdup("H");
}
return root;
}
int main(){
struct wrapper *root;
root = NULL;
root = walloc(root);
//free(root->data);
return 0;
}
Here is the Valgrind output:
$ valgrind --leak-check=full ./leak
==26489== Memcheck, a memory error detector
==26489== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==26489== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==26489== Command: ./leak
==26489==
==26489==
==26489== HEAP SUMMARY:
==26489== in use at exit: 2 bytes in 1 blocks
==26489== total heap usage: 2 allocs, 1 frees, 1,790 bytes allocated
==26489==
==26489== 2 bytes in 1 blocks are definitely lost in loss record 1 of 1
==26489== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26489== by 0x4EB79C9: strdup (in /usr/lib/libc-2.20.so)
==26489== by 0x400542: walloc (leak.c:13)
==26489== by 0x400542: main (leak.c:23)
==26489==
==26489== LEAK SUMMARY:
==26489== definitely lost: 2 bytes in 1 blocks
==26489== indirectly lost: 0 bytes in 0 blocks
==26489== possibly lost: 0 bytes in 0 blocks
==26489== still reachable: 0 bytes in 0 blocks
==26489== suppressed: 0 bytes in 0 blocks
==26489==
==26489== For counts of detected and suppressed errors, rerun with: -v
==26489== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
strdup allocates memory on the heap (using malloc) and therefore you need to free this memory when it's no longer in use like for anyone of your own direct call to malloc.
You must do that even when the program finish because this is the only way to detect a memory leak. Of course, the notion of checking for any memory leak might seem a little overkill when a program finish because all of its allocated memory is then automatically released by the OS but don't forget that your small program is an exception here. Usually, most programs will take a very large amount of memory when running and might run out of memory or run much slower if there are multiple memory leaks inside them.
Even a small program should be well written; otherwise it will become impossible for you to write any big programs later because your bad habits will translate into a tons of coding errors.
Thanks to #sharth for pointing me in the right direction. The Direct Loss was actually properly detected by Valgrind, but was confusing due to the -O3 compilation which removed root entirely. Compiling without -O3 shows the proper direct loss of 8 bytes and indirect loss of 2 bytes.
Also, thanks to #SylvainL and #Lundin for their best practices comments.
FYI: The corrected Valgrind output looks like this:
==30492== Memcheck, a memory error detector
==30492== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==30492== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==30492== Command: ./leak
==30492==
==30492==
==30492== HEAP SUMMARY:
==30492== in use at exit: 10 bytes in 2 blocks
==30492== total heap usage: 3 allocs, 1 frees, 1,830 bytes allocated
==30492==
==30492== 10 (8 direct, 2 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==30492== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30492== by 0x400687: walloc (leak.c:12)
==30492== by 0x4006C6: main (leak.c:23)
==30492==
==30492== LEAK SUMMARY:
==30492== definitely lost: 8 bytes in 1 blocks
==30492== indirectly lost: 2 bytes in 1 blocks
==30492== possibly lost: 0 bytes in 0 blocks
==30492== still reachable: 0 bytes in 0 blocks
==30492== suppressed: 0 bytes in 0 blocks
==30492==
==30492== For counts of detected and suppressed errors, rerun with: -v
==30492== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Memory leaks without allocating any memory

I was just testing out some c code I was writing and I found that I had a lot of memory leaks, so I wanted to see where they were coming from. All the code I had was:
int main() {
return 0;
}
Just a simple main that did nothing and I had all these memory leaks:
==38882== HEAP SUMMARY:
==38882== in use at exit: 58,678 bytes in 363 blocks
==38882== total heap usage: 514 allocs, 151 frees, 62,544 bytes allocated
==38882==
==38882== LEAK SUMMARY:
==38882== definitely lost: 8,624 bytes in 14 blocks
==38882== indirectly lost: 1,168 bytes in 5 blocks
==38882== possibly lost: 4,925 bytes in 68 blocks
==38882== still reachable: 43,961 bytes in 276 blocks
==38882== suppressed: 0 bytes in 0 blocks
==38882== Rerun with --leak-check=full to see details of leaked memory
==38882==
==38882== For counts of detected and suppressed errors, rerun with: -v
==38882== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
When I run this code on my university's computers I have no memory leaks. Is there something on my local machine that is causing this many memory leaks?
It is fine. Your program uses runtime library (i.e. libc or equivalent) and the library allocates some memory for own needs.
I get the same error on my Mac. It's either a valgrind problem or (more likely) a library problem on the Mac. I would suggest to use valgrind only on Linux.

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