So I have a php, ruby and python background and got started with C. I'm using Valgrind to check if my programs are not doing silly things but I get this kind of output quite frequently:
14072== <...VALGRIND HEADER & COPYRIGHT...>
14158== HEAP SUMMARY:
14158== in use at exit: 137,084 bytes in 196 blocks
14158== total heap usage: 247 allocs, 51 frees, 149,496 bytes allocated
14158==
14158== 7 bytes in 1 blocks are definitely lost in loss record 3 of 74 at
14158== 0x4C2745D: malloc in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so
14158== by 0x50F3369: strdup in /usr/lib64/libc-2.18.so
14158== by 0x4E51B34: readline in /usr/lib64/libedit.so.0.0.43
14158== by 0x40083C: main in /home/<program location>/
14158==
14158== LEAK SUMMARY:
14158== definitely lost: 7 bytes in 1 blocks
14158== indirectly lost: 0 bytes in 0 blocks
14158== possibly lost: 0 bytes in 0 blocks
14158== still reachable: 137,077 bytes in 195 blocks
14158== suppressed: 0 bytes in 0 blocks
14158== Reachable blocks (those to which a pointer was found) are not shown.
14158== To see them, rerun with: --leak-check=full --show-leak-kinds=all
14158==
14158== For counts of detected and suppressed errors, rerun with: -v
14158== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
This valgrind debug output is from this quick REPL that simply shouts back user input on the screen or quits in case input equals to :exit:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <editline/readline.h>
static char prompt[5] = "repl>";
static char* cmd_exit = ":exit";
int main(int argc, char** argv) {
puts("Press Ctrl+c to Exit\n");
while(1) {
char* input = readline(prompt);
add_history(input);
if(strcmp(input,cmd_exit) == 0) {
puts("Bye!");
return 0;
}
printf("%s\n", input);
free(input);
}
return 0;
}
I've already tried to free both prompt and cmd_exit variables before function main returns a value but leak is still there according to Valgrind.
...
free(prompt);
free(cmd_exit);
return 0;
}
Some questions:
How to get rid of this reported memory leak?
Should I be using static variables in this situation?
Should I free those static variables too?
Any good advice or material is welcome.
You only need to free things you malloced, so you don't need to free the static variables.
As your readline function seems to use strdup and that uses malloc/calloc, you need to free input. You do this in the loop which is good, but you missed it when you exit the loop:
if(strcmp(input,cmd_exit) == 0) {
puts("Bye!");
free(input);
return 0;
}
By the way:
static char prompt[6] = "repl>";
The text "repl>" has 6 chars, r, e, p, l, > and a nul byte to mark the end of the string.
Related
For the past 2 hours or so, I have been trying to figure out why the following code throws a "possibly lost" memory leak:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <readline/readline.h>
#include <readline/history.h>
void *my_read(void* arg) {
char* buf;
if ((buf = readline(">> ")) != NULL) {
printf("Test\n");
if (strlen(buf) > 0) {
add_history(buf);
}
free(buf);
}
pthread_exit(0);
}
int main(int argc, char** argv) {
rl_catch_signals = 0;
pthread_t thread;
pthread_create(&thread, NULL, my_read, NULL);
pthread_join(thread, NULL);
return 0;
}
And I have also tried using detach instead of join, but the result is the same, which is:
==1498903== 272 bytes in 1 blocks are possibly lost in loss record 31 of 78
==1498903== at 0x4849C0F: calloc (vg_replace_malloc.c:1328)
==1498903== by 0x4012662: allocate_dtv (in /lib64/ld-linux-x86-64.so.2)
==1498903== by 0x401309D: _dl_allocate_tls (in /lib64/ld-linux-x86-64.so.2)
==1498903== by 0x497FAA4: pthread_create##GLIBC_2.34 (in /lib64/libc.so.6)
==1498903== by 0x10927B: main (in /home/user/readline)
I have also tried just straight up allocating memory and freeing it in a loop, which shows the same result.
EDIT: Picked the read -> my_read fix from Ajay, but the main issue still remains.
The main problem here is that you have defined a function named read. Readline internally calls the read function to read from stdin. This ends up recursively calling your read function leading to a stackoverflow and crashing your program. The crashed program doesn't free memory for the pthread_t state which should be done when you call pthread_join. This is the main reason valgrind complains.
A simple fix is to read --> my_read.
With the proposed fix the output of valgrind --leak-check=full on my end is -
==27167== Memcheck, a memory error detector
==27167== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27167== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==27167== Command: ./test
==27167==
>> hello
Test
==27167==
==27167== HEAP SUMMARY:
==27167== in use at exit: 134,297 bytes in 195 blocks
==27167== total heap usage: 316 allocs, 121 frees, 155,633 bytes allocated
==27167==
==27167== LEAK SUMMARY:
==27167== definitely lost: 0 bytes in 0 blocks
==27167== indirectly lost: 0 bytes in 0 blocks
==27167== possibly lost: 0 bytes in 0 blocks
==27167== still reachable: 134,297 bytes in 195 blocks
==27167== suppressed: 0 bytes in 0 blocks
==27167== Reachable blocks (those to which a pointer was found) are not shown.
==27167== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==27167==
==27167== For counts of detected and suppressed errors, rerun with: -v
==27167== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
I using valgrind to find a leak of memory. I wrote a function "prefix_to_string" to concatenate any two strings, but when I use the command
valgrind --leak-check=full ./helloworld
it says that I have a lot of leaks of memory. I really don't know where and why. I asked a friend why it was happening and he says that it was for doing malloc 2 times, 1 out the function and 1 in the function, but I don't know how to take care of that leak, because I think that I need to do those memory requests.
Here is the output that Valgrind gives me:
==9078== Memcheck, a memory error detector
==9078== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9078== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9078== Command: ./holamundo
==9078==
==9078== error calling PR_SET_PTRACER, vgdb might block
150:62
bye
==9078==
==9078== HEAP SUMMARY:
==9078== in use at exit: 63 bytes in 4 blocks
==9078== total heap usage: 5 allocs, 1 frees, 575 bytes allocated
==9078==
==9078== 5 bytes in 1 blocks are definitely lost in loss record 1 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008AC: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 7 bytes in 1 blocks are definitely lost in loss record 2 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008C3: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 8 bytes in 1 blocks are definitely lost in loss record 3 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008D8: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 43 bytes in 1 blocks are definitely lost in loss record 4 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400897: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== LEAK SUMMARY:
==9078== definitely lost: 63 bytes in 4 blocks
==9078== indirectly lost: 0 bytes in 0 blocks
==9078== possibly lost: 0 bytes in 0 blocks
==9078== still reachable: 0 bytes in 0 blocks
==9078== suppressed: 0 bytes in 0 blocks
==9078==
==9078== For counts of detected and suppressed errors, rerun with: -v
==9078== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
and here is the main of my code, so this way you can reproduce the problem:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
char* prefix_to_string(char* first_string,char* second_string){
char* name = first_string;
char* extension = second_string;
char* name_with_extension;
name_with_extension = malloc(strlen(name)*(sizeof(char))+strlen(extension)*(sizeof(char))+1); /* make space for the new string (should check the return value ...) */
strcpy(name_with_extension, name); /* copy name into the new var */
strcat(name_with_extension, extension); /* add the extension */
return name_with_extension;
}
static char *itoa_simple_helper(char *dest, int i) {
if (i <= -10) {
dest = itoa_simple_helper(dest, i/10);
}
*dest++ = '0' - i%10;
return dest;
}
char *itoa_simple(char *dest, int i) {
char *s = dest;
if (i < 0) {
*s++ = '-';
} else {
i = -i;
}
*itoa_simple_helper(s, i) = '\0';
return dest;
}
int main(int argc, char *argv[]) {
int idx = 150;
int id = 62;
char str_idx[20];
char str_id[20];
itoa_simple( str_idx ,idx);
itoa_simple( str_id,id);
char *text_to_write;
text_to_write = malloc(2+sizeof(str_id)+sizeof(str_idx)+1);
text_to_write = prefix_to_string(str_idx,":");
text_to_write = prefix_to_string(text_to_write,str_id);
text_to_write = prefix_to_string(text_to_write,"\n");
printf("%s",text_to_write);
printf("bye\n");
free(text_to_write);
return 1;
}
You don't call free() often enough — you can't expect to avoid memory leaks if you don't call free() to release each separate memory allocation. And your repeated assignments to text_to_write in main() mean that you discard the only pointers to some of the allocated memory, so you can't free what was allocated. C requires endless care with memory management.
You have:
char *text_to_write;
text_to_write = malloc(2+sizeof(str_id)+sizeof(str_idx)+1);
// This assignment throws away the memory from the previous malloc
text_to_write = prefix_to_string(str_idx,":");
// This assignment throws away the memory from the previous prefix_to_string
text_to_write = prefix_to_string(text_to_write,str_id);
// This assignment also throws away the memory from the previous prefix_to_string
text_to_write = prefix_to_string(text_to_write,"\n");
printf("%s",text_to_write);
printf("bye\n");
// Calling free here only releases the last allocation from prefix_to_string
free(text_to_write);
You need something more like:
char *part1 = prefix_to_string(str_idx, ":");
char *part2 = prefix_to_string(part1, str_id);
char *part3 = prefix_to_string(part2, "\n");
printf("%s", part3);
printf("bye\n");
free(part1);
free(part2);
free(part3);
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.
I have a multi-threaded application which uses joinable threads.
In order to create the threads (which are in total nthreads workers+1 additional thread) I use a regular call to pthread_create.
However, when I try to debug memory leaks, I get a x bytes in y blocks are possibly lost in loss record z of w error, caused by the pthread_create calls.
Here is the part of the code of the program relevant to the issue :
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
int main(){
int i=0;
int nthreads=8;
pthread_t tid_w[nthreads+1];
if( pthread_create(&tid_w[0], NULL, dispatcher, (void*) (size_t) i)<0){
perror("Creating dispatcher thread");
return -1;
}
for(i=1; i<nthreads+1; i++){
if( pthread_create(&tid_w[i], NULL, worker, (void*) (size_t) i)<0){
perror("Creating worker thread");
return -1;
}
}
// thread joining
for(i=0; i<nthreads+1; i++){
if( pthread_join(tid_w[i], NULL)<0){
perror("Joining thread");
return -1;
}
}
return 0;
}
This is the output of valgrind (3.11)
==14418==
==14418== HEAP SUMMARY:
==14418== in use at exit: 14,496 bytes in 21 blocks
==14418== total heap usage: 25 allocs, 4 frees, 15,724 bytes allocated
==14418==
==14418== 560 bytes in 1 blocks are possibly lost in loss record 12 of 14
==14418== at 0x4C2DB95: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14418== by 0x40134C4: allocate_dtv (dl-tls.c:322)
==14418== by 0x40134C4: _dl_allocate_tls (dl-tls.c:544)
==14418== by 0x4E400D2: allocate_stack (allocatestack.c:588)
==14418== by 0x4E400D2: pthread_create##GLIBC_2.2.5 (pthread_create.c:537)
==14418== by 0x4018AE: main (chatty.c:132)
==14418==
==14418== 4,480 bytes in 8 blocks are possibly lost in loss record 13 of 14
==14418== at 0x4C2DB95: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14418== by 0x40134C4: allocate_dtv (dl-tls.c:322)
==14418== by 0x40134C4: _dl_allocate_tls (dl-tls.c:544)
==14418== by 0x4E400D2: allocate_stack (allocatestack.c:588)
==14418== by 0x4E400D2: pthread_create##GLIBC_2.2.5 (pthread_create.c:537)
==14418== by 0x401909: main (chatty.c:138)
==14418==
==14418== LEAK SUMMARY:
==14418== definitely lost: 0 bytes in 0 blocks
==14418== indirectly lost: 0 bytes in 0 blocks
==14418== possibly lost: 5,040 bytes in 9 blocks
==14418== still reachable: 9,456 bytes in 12 blocks
==14418== suppressed: 0 bytes in 0 blocks
==14418== Reachable blocks (those to which a pointer was found) are not shown.
==14418== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==14418==
==14418== For counts of detected and suppressed errors, rerun with: -v
==14418== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Line numbers might not match because I have removed a few socket-related parts from the code.
I also have read a lot about pthread_create causing memory leaks but it seems like the issue presents itself when in use of detached threads, which is not my case.
Any idea on how to solve the issue?
I have a simple piece of a program thats currently producing some memory leaks according to valgrind and I'm not sure why:
char *filename = strrchr(argv[3], "/") + 1;
file = fopen(fileName, "w");
So as far as I know, I give the program an argv[3] of "test/test2", and the first line finds the last occurrence of "/", and then moves one character forward (to "t"). Then the second line opens a file that is a pointer to the char array "test".
Why is this causing a memory leak?
If you use the opened file stream, there's a good chance that the Standard I/O library will allocate a buffer for the stream. If you don't explicitly close the stream, there's a good chance that valgrind will regard that memory as still in use; there is an outside chance it would be regarded as leaked.
What is the exact message from valgrind? Why are you pointing at fopen()?
Consider this trivial program:
#include <stdio.h>
static void leaky(void)
{
FILE *fp = fopen("/etc/passwd", "r");
char buffer[2048];
while (fgets(buffer, sizeof(buffer), fp) != 0)
fputs(buffer, stdout);
/* fclose(fp); */
}
int main(void)
{
leaky();
return 0;
}
It produces the summary output:
==6169==
==6169== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 5 from 1)
==6169== malloc/free: in use at exit: 568 bytes in 1 blocks.
==6169== malloc/free: 1 allocs, 0 frees, 568 bytes allocated.
==6169== For counts of detected errors, rerun with: -v
==6169== searching for pointers to 1 not-freed blocks.
==6169== checked 69,424 bytes.
==6169==
==6169== LEAK SUMMARY:
==6169== definitely lost: 0 bytes in 0 blocks.
==6169== possibly lost: 0 bytes in 0 blocks.
==6169== still reachable: 568 bytes in 1 blocks.
==6169== suppressed: 0 bytes in 0 blocks.
==6169== Reachable blocks (those to which a pointer was found) are not shown.
==6169== To see them, rerun with: --show-reachable=yes
With the fclose(fp) not commented out, the output is:
==7125==
==7125== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 5 from 1)
==7125== malloc/free: in use at exit: 0 bytes in 0 blocks.
==7125== malloc/free: 1 allocs, 1 frees, 568 bytes allocated.
==7125== For counts of detected errors, rerun with: -v
==7125== All heap blocks were freed -- no leaks are possible.
Well, your code would leak a file handle (the latter fopen is not closed). However, without a more complete example its hard to tell.