I've tried the following code on GeoIP 1.4.8 and 1.6.6 and it's only freeing 5 allocs out of 40 allocs reported by valgrind.
I'm aware of the "still reachable" according to this post, but I want to make sure that's the case in here. It does seem odd to me is only freeing 5 allocs. Any ideas?
==1687== HEAP SUMMARY:
==1687== in use at exit: 35,128 bytes in 35 blocks
==1687== total heap usage: 40 allocs, 5 frees, 36,847 bytes allocated
==1687==
==1687== 312 bytes in 1 blocks are still reachable in loss record 1 of 35
==1687== at 0x4C2C947: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1687== by 0x4E3DA5E: _GeoIP_setup_dbfilename (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x4E3E789: GeoIP_new (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x40075E: main (in /home/pixie/a.out)
==1687==
==1687== 1,024 bytes in 1 blocks are still reachable in loss record 2 of 35
==1687== at 0x4C2C947: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1687== by 0x4E3D9A5: _GeoIP_full_path_to (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x4E3DA70: _GeoIP_setup_dbfilename (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x4E3E789: GeoIP_new (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x40075E: main (in /home/pixie/a.out)
==1687==
==1687== 1,024 bytes in 1 blocks are still reachable in loss record 3 of 35
==1687== at 0x4C2C947: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1687== by 0x4E3D9A5: _GeoIP_full_path_to (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x4E3DA83: _GeoIP_setup_dbfilename (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x4E3E789: GeoIP_new (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x40075E: main (in /home/pixie/a.out)
==1687==
==1687== 1,024 bytes in 1 blocks are still reachable in loss record 4 of 35
==1687== at 0x4C2C947: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1687== by 0x4E3D9A5: _GeoIP_full_path_to (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x4E3DA96: _GeoIP_setup_dbfilename (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x4E3E789: GeoIP_new (in /usr/lib/libGeoIP.so.1.6.6)
==1687== by 0x40075E: main (in /home/pixie/a.out)
...
Code
#include <GeoIP.h>
int main (int argc, char **argv) {
GeoIP * gp;
gp = GeoIP_new(GEOIP_STANDARD);
printf("%s\n", GeoIP_country_code_by_addr(gp, "216.58.216.238"));
GeoIP_delete(gp);
return 0;
}
Apparently the following call does the job (not documented).
GeoIP_cleanup();
Related
I am currently working on cs50 pset5.
I have encountered a memory leak when I attempt to free all the memory I have located in the program.
The error seems to occur in my unload function, where it malloc for pointer cursor.
If anyone can provide me directions on how to approach this issue, please let me know.
I have also provided comments to my code to highlight what it is doing.
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = 50;
node *table[N] = {NULL};
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// allocate memory for struct type `node` pointer
node *cursor = (node*)malloc(sizeof(node)); // MEMORY LEAK happens here !!!! :(
node *tmp = (node*)malloc(sizeof(node));
// if memory cannot be allocated successfully, return false
if (cursor == NULL || tmp == NULL)
{
return false;
}
// iterate the table for N'times (N = 50, for now)
for (int i = 0; i < N; i++)
{
// if the table has nothing inside the i'th bucket, return false
// this means, table has no linked list inside i'th bucket
if (table[i] == NULL)
{
continue;
}
else
{
// assign tmp pointer to the head node, and cursor to anything next to tmp
tmp = table[i];
cursor = tmp;
cursor = cursor->next;
// free memory for tmp pointer
free(tmp);
// continue traversing the linked list until cursor pointer points to NULL (end of the linked list)
while (cursor != NULL)
{
tmp = cursor;
cursor = cursor->next;
free(tmp);
}
}
}
// free memory for cursor
free(cursor);
return true;
}
The error I get, after running, help50 valgrind ./speller dictionaries/small texts/cat.txt.
==14685== Memcheck, a memory error detector
==14685== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14685== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14685== Command: ./speller dictionaries/small texts/cat.txt
==14685==
32
==14685== Invalid write of size 1
==14685== at 0x40121F: hash (dictionary.c:67)
==14685== by 0x401354: load (dictionary.c:99)
==14685== by 0x400A2B: main (speller.c:41)
==14685== Address 0x55cc88a is 2 bytes after a block of size 8 alloc'd
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x4011D5: hash (dictionary.c:61)
==14685== by 0x401354: load (dictionary.c:99)
==14685== by 0x400A2B: main (speller.c:41)
==14685==
==14685== Invalid read of size 1
==14685== at 0x40122C: hash (dictionary.c:68)
==14685== by 0x401354: load (dictionary.c:99)
==14685== by 0x400A2B: main (speller.c:41)
==14685== Address 0x55cc88a is 2 bytes after a block of size 8 alloc'd
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x4011D5: hash (dictionary.c:61)
==14685== by 0x401354: load (dictionary.c:99)
==14685== by 0x400A2B: main (speller.c:41)
==14685==
19
MISSPELLED WORDS
47
A
32
20
is
27
not
47
a
==14685== Invalid write of size 1
==14685== at 0x40121F: hash (dictionary.c:67)
==14685== by 0x401124: check (dictionary.c:32)
==14685== by 0x400D50: main (speller.c:114)
==14685== Address 0x55cdf9a is 2 bytes after a block of size 8 alloc'd
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x4011D5: hash (dictionary.c:61)
==14685== by 0x401124: check (dictionary.c:32)
==14685== by 0x400D50: main (speller.c:114)
==14685==
==14685== Invalid read of size 1
==14685== at 0x40122C: hash (dictionary.c:68)
==14685== by 0x401124: check (dictionary.c:32)
==14685== by 0x400D50: main (speller.c:114)
==14685== Address 0x55cdf9a is 2 bytes after a block of size 8 alloc'd
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x4011D5: hash (dictionary.c:61)
==14685== by 0x401124: check (dictionary.c:32)
==14685== by 0x400D50: main (speller.c:114)
==14685==
19
WORDS MISSPELLED: 4
WORDS IN DICTIONARY: 2
WORDS IN TEXT: 6
TIME IN load: 0.03
TIME IN check: 0.00
TIME IN size: 0.00
TIME IN unload: 0.00
TIME IN TOTAL: 0.03
==14685==
==14685== HEAP SUMMARY:
==14685== in use at exit: 1,000 bytes in 9 blocks
==14685== total heap usage: 23 allocs, 14 frees, 10,944 bytes allocated
==14685==
==14685== 56 bytes in 1 blocks are definitely lost in loss record 1 of 4
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x4013F1: unload (dictionary.c:128)
==14685== by 0x400ED0: main (speller.c:154)
==14685==
==14685== 56 bytes in 1 blocks are definitely lost in loss record 2 of 4
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x4013FF: unload (dictionary.c:129)
==14685== by 0x400ED0: main (speller.c:154)
==14685==
==14685== 336 bytes in 6 blocks are definitely lost in loss record 3 of 4
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x401131: check (dictionary.c:33)
==14685== by 0x400D50: main (speller.c:114)
==14685==
==14685== 552 bytes in 1 blocks are still reachable in loss record 4 of 4
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x5258E49: __fopen_internal (iofopen.c:65)
==14685== by 0x5258E49: fopen##GLIBC_2.2.5 (iofopen.c:89)
==14685== by 0x4012DE: load (dictionary.c:83)
==14685== by 0x400A2B: main (speller.c:41)
==14685==
==14685== LEAK SUMMARY:
==14685== definitely lost: 448 bytes in 8 blocks
==14685== indirectly lost: 0 bytes in 0 blocks
==14685== possibly lost: 0 bytes in 0 blocks
==14685== still reachable: 552 bytes in 1 blocks
==14685== suppressed: 0 bytes in 0 blocks
==14685==
==14685== For counts of detected and suppressed errors, rerun with: -v
==14685== ERROR SUMMARY: 15 errors from 7 contexts (suppressed: 0 from 0)
Asking for help...
==14685== 56 bytes in 1 blocks are definitely lost in loss record 1 of 4
==14685== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14685== by 0x4013F1: unload (dictionary.c:128)
==14685== by 0x400ED0: main (speller.c:154)
Looks like your program leaked 56 bytes of memory. Did you forget to free memory that you allocated via malloc? Take a closer look at line 128 of dictionary.c.
So why does memory leak happen?
A memory leak happens when a programmer creates a memory from heap but forgets to free it.
However, in my code, I have free'd both cursor and tmp pointer after it's used.
I do not know why I am encountering the error, although I am freeing it at the end of the function.
Yes, "MEMORY LEAK happens here !!!!" as you say.
You allocated two buffers, but later their pointers are overwritten by table[i] without being freed. This is memory leak.
To avoid memory leak, stop allocating unused buffers.
The part
// allocate memory for struct type `node` pointer
node *cursor = (node*)malloc(sizeof(node)); // MEMORY LEAK happens here !!!! :(
node *tmp = (node*)malloc(sizeof(node));
// if memory cannot be allocated successfully, return false
if (cursor == NULL || tmp == NULL)
{
return false;
}
should be just
// allocate memory for struct type `node` pointer
node *cursor;
node *tmp;
The memory for pointer is allocated on the stack.
Also the part
// free memory for cursor
free(cursor);
should be removed because the list is already freed and the memory for cursor will be automatically freed (from the stack) on returning from the function.
I'm doing an exercise, in which among other things, I have to read the configuration info from a txt file, and use them to set up a server. My code seems to work, the server starts correctly and the various buffers contain the information taken from the file, but starting my program with valgrind returns these errors, I can not understand what I'm wrong.
this is the main
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <config.h>
char* UNIXPATH1=NULL;
void cleanup(){
if(UNIXPATH1!=NULL)
unlink(UNIXPATH1);
}
int main(int argc, char *argv[]) {
FILE *fileconf=fopen("./try/in.txt","r");
if(fileconf==NULL){
fprintf(stderr, "File error\n");
return -1;
}
set_conf(fileconf);
UNIXPATH1=malloc(strlen(returnUnixpath())*sizeof(char));
strncpy(UNIXPATH1,returnUnixpath(),strlen(returnUnixpath()));
cleanup();
atexit(cleanup);
FILE *fileout=fopen(UNIXPATH1,"w");
if(fileout==NULL){
fprintf(stderr, "File error\n");
return -1;
}
fputs("hello",fileout);
fclose(fileout);
free(UNIXPATH1);
return 0;
}
this is config.h
#include <errno.h>
#include <stdlib.h>
#define MEM_ALL(r,c,msg) \
if(!(r=c)) {perror(msg); fprintf(stderr, "ERROR: Out of memory\n"); exit(errno); }
typedef int make_iso_compilers_happy;
char* UNIXPATH;
char* returnUnixpath(){
return UNIXPATH;
}
void set_conf(FILE *file){
char buffer[4096];
char* token1;
char* saveptr1;
char *array[3];
int i;
for(i=0;i<3;i++){
MEM_ALL(array[i],malloc(1*sizeof(char)),"malloc array[i]");
}
i=0;
char* tmp=malloc(sizeof(char));
while(fgets(buffer,4096,file)!=NULL){
if(buffer[0]!='#' && buffer[0]!='\n' && buffer[0]!=' '){
buffer[strlen(buffer)-1]='\0';
token1=strtok_r(buffer," ",&saveptr1);
printf("s: %ld",strlen(token1));
tmp=realloc(tmp,(strlen(token1))*sizeof(char));
strncpy(tmp,token1,(strlen(token1)));
for(i=0;i<3;i++){
MEM_ALL(array[i],realloc(array[i],(strlen(token1)+1)*sizeof(char)),"realloc array[i]");
strncpy(array[i],token1,(strlen(token1)+1));
array[i][strlen(token1)]='\0';
if(i!=2)
token1=strtok_r(NULL," ",&saveptr1);
}
if(strncmp("UnixPath",tmp,8)==0){
MEM_ALL(UNIXPATH,malloc(strlen(array[2])*sizeof(char)),"malloc unixpath");
strncpy(UNIXPATH,array[2],strlen(array[2]));
}
}
}
free(tmp);
for(i=0;i<3;i++){
free(array[i]);
}
fclose(file);
}
this is the in.txt file
UnixPath = ./try/o.txt
and this is valgrind output
==5897== Invalid read of size 1
==5897== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x10905C: main (main.c:26)
==5897== Address 0x522e9bb is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x108EB7: set_conf (config.h:44)
==5897== by 0x10904A: main (main.c:25)
==5897==
==5897== Invalid read of size 1
==5897== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x10907D: main (main.c:27)
==5897== Address 0x522e9bb is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x108EB7: set_conf (config.h:44)
==5897== by 0x10904A: main (main.c:25)
==5897==
==5897== Syscall param unlink(pathname) points to unaddressable byte(s)
==5897== at 0x4F4DD47: unlink (syscall-template.S:78)
==5897== by 0x108FE3: cleanup (main.c:14)
==5897== by 0x1090AC: main (main.c:29)
==5897== Address 0x522ea0b is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
==5897== Syscall param openat(filename) points to unaddressable byte(s)
==5897== at 0x4F4BC8E: open (open64.c:47)
==5897== by 0x4EC8589: _IO_file_open (fileops.c:189)
==5897== by 0x4EC8589: _IO_file_fopen##GLIBC_2.2.5 (fileops.c:281)
==5897== by 0x4EBAEA9: __fopen_internal (iofopen.c:78)
==5897== by 0x4EBAEA9: fopen##GLIBC_2.2.5 (iofopen.c:89)
==5897== by 0x1090CE: main (main.c:32)
==5897== Address 0x522ea0b is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
==5897== Syscall param unlink(pathname) points to unaddressable byte(s)
==5897== at 0x4F4DD47: unlink (syscall-template.S:78)
==5897== by 0x108FE3: cleanup (main.c:14)
==5897== by 0x4E7F040: __run_exit_handlers (exit.c:108)
==5897== by 0x4E7F139: exit (exit.c:139)
==5897== by 0x4E5DB9D: (below main) (libc-start.c:344)
==5897== Address 0x522ea00 is 0 bytes inside a block of size 11 free'd
==5897== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109138: main (main.c:40)
==5897== Block was alloc'd at
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
s: 8==5897==
==5897== HEAP SUMMARY:
==5897== in use at exit: 11 bytes in 1 blocks
==5897== total heap usage: 15 allocs, 14 frees, 10,377 bytes allocated
==5897==
==5897== LEAK SUMMARY:
==5897== definitely lost: 0 bytes in 0 blocks
==5897== indirectly lost: 0 bytes in 0 blocks
==5897== possibly lost: 0 bytes in 0 blocks
==5897== still reachable: 11 bytes in 1 blocks
==5897== suppressed: 0 bytes in 0 blocks
==5897== Rerun with --leak-check=full to see details of leaked memory
Replace all the forms using strncpy like
UNIXPATH1=malloc(strlen(returnUnixpath())*sizeof(char));
strncpy(UNIXPATH1,returnUnixpath(),strlen(returnUnixpath()));
by a use of strdup
UNIXPATH1=strdup(returnUnixpath());
as you can see this is very more practical and this also fix the problem of the final character missing in your case. Of course remove array[i][strlen(token1)]='\0'; now useless.
Replace forms like :
tmp=realloc(tmp,(strlen(token1))*sizeof(char));
strncpy(tmp,token1,(strlen(token1)));
by
tmp=realloc(tmp, strlen(token1) + 1);
strcpy(tmp,token1);
Because of the atexit(cleanup); after free(UNIXPATH1); you need to do UNIXPATH1 = NULL; in main else cleanup access to the freed string at the end of main execution.
Other remarks :
by definition sizeof(char) is 1
it is strange to put code in a header file, if you cut code in several files use several source files
when you #include one of your header use "file.h" rather than <file.h>
After the changes the execution under valgrind doesn't signal invalid accesses
I've been getting this error whenever i run a full valgrind memory leak check and I really can't tell where the source of this error is. My code is running and appears to be correct but i've been getting this error since. Any advice would be much appreciated, thank you!
==2312== HEAP SUMMARY:
==2312== in use at exit: 26,325 bytes in 190 blocks
==2312== total heap usage: 20,531 allocs, 20,341 frees, 197,089 bytes allocated
==2312==
==2312== Searching for pointers to 190 not-freed blocks
==2312== Checked 9,805,752 bytes
==2312==
==2312== 272 (80 direct, 192 indirect) bytes in 1 blocks are definitely lost in loss record 53 of 67
==2312== at 0x100009EBB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==2312== by 0x1001C44A2: __Balloc_D2A (in /usr/lib/system/libsystem_c.dylib)
==2312== by 0x1001C4DEB: __d2b_D2A (in /usr/lib/system/libsystem_c.dylib)
==2312== by 0x1001C1443: __dtoa (in /usr/lib/system/libsystem_c.dylib)
==2312== by 0x1001EA07A: __vfprintf (in /usr/lib/system/libsystem_c.dylib)
==2312== by 0x10021335C: __v2printf (in /usr/lib/system/libsystem_c.dylib)
==2312== by 0x1001E901D: vfprintf_l (in /usr/lib/system/libsystem_c.dylib)
==2312== by 0x1001E6EB7: printf (in /usr/lib/system/libsystem_c.dylib)
==2312== by 0x100001B02: main (in ./tldmonitor)
==2312==
==2312== LEAK SUMMARY:
==2312== definitely lost: 80 bytes in 1 blocks
==2312== indirectly lost: 192 bytes in 5 blocks
==2312== possibly lost: 0 bytes in 0 blocks
==2312== still reachable: 0 bytes in 0 blocks
==2312== suppressed: 26,053 bytes in 184 blocks
==2312==
==2312== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 16 from 16)
--2312--
--2312-- used_suppression: 1 OSX1011:21-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:944 suppressed: 4,096 bytes in 1 blocks
--2312-- used_suppression: 1 OSX1011:15-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:886 suppressed: 4,096 bytes in 1 blocks
--2312-- used_suppression: 10 OSX1011:17-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:906 suppressed: 3,392 bytes in 55 blocks
--2312-- used_suppression: 3 OSX1011:16-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:897 suppressed: 2,816 bytes in 44 blocks
--2312-- used_suppression: 2 OSX1011:4-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:778 suppressed: 4,152 bytes in 2 blocks
--2312-- used_suppression: 2 OSX1011:19-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:924 suppressed: 2,592 bytes in 2 blocks
--2312-- used_suppression: 7 OSX1011:7-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:808 suppressed: 1,680 bytes in 22 blocks
--2312-- used_suppression: 11 OSX1011:18-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:915 suppressed: 2,312 bytes in 11 blocks
--2312-- used_suppression: 20 OSX1011:10-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:839 suppressed: 2,461 bytes in 39 blocks
--2312-- used_suppression: 2 OSX1011:8-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:819 suppressed: 520 bytes in 2 blocks
--2312-- used_suppression: 2 OSX1011:20-Leak /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/default.supp:934 suppressed: 224 bytes in 5 blocks
==2312==
==2312== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 16 from 16)
After i generate a suppression block:
==2317== HEAP SUMMARY:
==2317== in use at exit: 26,325 bytes in 190 blocks
==2317== total heap usage: 20,531 allocs, 20,341 frees, 197,089 bytes allocated
==2317==
==2317== Searching for pointers to 190 not-freed blocks
==2317== Checked 9,805,752 bytes
==2317==
==2317== 272 (80 direct, 192 indirect) bytes in 1 blocks are definitely lost in loss record 53 of 67
==2317== at 0x100009EBB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==2317== by 0x1001C44A2: __Balloc_D2A (in /usr/lib/system/libsystem_c.dylib)
==2317== by 0x1001C4DEB: __d2b_D2A (in /usr/lib/system/libsystem_c.dylib)
==2317== by 0x1001C1443: __dtoa (in /usr/lib/system/libsystem_c.dylib)
==2317== by 0x1001EA07A: __vfprintf (in /usr/lib/system/libsystem_c.dylib)
==2317== by 0x10021335C: __v2printf (in /usr/lib/system/libsystem_c.dylib)
==2317== by 0x1001E901D: vfprintf_l (in /usr/lib/system/libsystem_c.dylib)
==2317== by 0x1001E6EB7: printf (in /usr/lib/system/libsystem_c.dylib)
==2317== by 0x100001B02: main (in ./tldmonitor)
==2317==
==2317==
Turns out it was a false leak, tested my code on a linux virtual machine and no errors. Thanks.
The following code compiles correctly and valgrind reports no leaks:
# include <libxml/encoding.h>
# include <libxml/xmlwriter.h>
int main(void) {
xmlTextWriterPtr XMLWriter = xmlNewTextWriterFilename("example.xml", 0);
xmlTextWriterStartDocument(XMLWriter, NULL, NULL, NULL);
xmlTextWriterEndDocument(XMLWriter);
xmlFreeTextWriter(XMLWriter);
xmlCleanupParser();
return 0;
}
-----------------------------------------
==26059== HEAP SUMMARY:
==26059== in use at exit: 0 bytes in 0 blocks
==26059== total heap usage: 16 allocs, 16 frees, 4,774 bytes allocated
==26059==
==26059== All heap blocks were freed -- no leaks are possible
Once the encoding is specified in the xmlNewTextWriterFilename call, however, hilary ensues:
# include <libxml/encoding.h>
# include <libxml/xmlwriter.h>
int main(void) {
xmlTextWriterPtr XMLWriter = xmlNewTextWriterFilename("example.xml", 0);
xmlTextWriterStartDocument(XMLWriter, NULL, "UTF-8", NULL);
xmlTextWriterEndDocument(XMLWriter);
xmlFreeTextWriter(XMLWriter);
xmlCleanupParser();
return 0;
}
-----------------------------------------
==26082== HEAP SUMMARY:
==26082== in use at exit: 422 bytes in 17 blocks
==26082== total heap usage: 36 allocs, 19 frees, 9,224 bytes allocated
==26082==
==26082== 5 bytes in 1 blocks are still reachable in loss record 1 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x40EC23B: xmlStrndup (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x494942FF: ???
==26082==
==26082== 6 bytes in 1 blocks are still reachable in loss record 2 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x40EC23B: xmlStrndup (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x37: ???
==26082==
==26082== 6 bytes in 1 blocks are still reachable in loss record 3 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x40EC23B: xmlStrndup (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x39350048: ???
==26082==
==26082== 7 bytes in 1 blocks are still reachable in loss record 4 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x40EC23B: xmlStrndup (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x45003630: ???
==26082==
==26082== 9 bytes in 1 blocks are still reachable in loss record 5 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x40EC23B: xmlStrndup (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x454C3630: ???
==26082==
==26082== 9 bytes in 1 blocks are still reachable in loss record 6 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x40EC23B: xmlStrndup (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x45423630: ???
==26082==
==26082== 9 bytes in 1 blocks are still reachable in loss record 7 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x40EC23B: xmlStrndup (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x49494352: ???
==26082==
==26082== 11 bytes in 1 blocks are still reachable in loss record 8 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x40EC23B: xmlStrndup (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x39353837: ???
==26082==
==26082== 20 bytes in 1 blocks are still reachable in loss record 9 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406E9D1: xmlNewCharEncodingHandler (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x406EB28: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== 20 bytes in 1 blocks are still reachable in loss record 10 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406E9D1: xmlNewCharEncodingHandler (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x406EB44: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== 20 bytes in 1 blocks are still reachable in loss record 11 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406E9D1: xmlNewCharEncodingHandler (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x406EB6C: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== 20 bytes in 1 blocks are still reachable in loss record 12 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406E9D1: xmlNewCharEncodingHandler (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x406EB94: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== 20 bytes in 1 blocks are still reachable in loss record 13 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406E9D1: xmlNewCharEncodingHandler (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x406EBB6: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== 20 bytes in 1 blocks are still reachable in loss record 14 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406E9D1: xmlNewCharEncodingHandler (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x406EBCC: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== 20 bytes in 1 blocks are still reachable in loss record 15 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406E9D1: xmlNewCharEncodingHandler (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x406EBE2: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== 20 bytes in 1 blocks are still reachable in loss record 16 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406E9D1: xmlNewCharEncodingHandler (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x406EC02: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== 200 bytes in 1 blocks are still reachable in loss record 17 of 17
==26082== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==26082== by 0x406EABE: xmlInitCharEncodingHandlers (in /usr/lib/i386-linux-gnu/libxml2.so.2.7.8)
==26082== by 0x41B54D2: (below main) (libc-start.c:226)
==26082==
==26082== LEAK SUMMARY:
==26082== definitely lost: 0 bytes in 0 blocks
==26082== indirectly lost: 0 bytes in 0 blocks
==26082== possibly lost: 0 bytes in 0 blocks
==26082== still reachable: 422 bytes in 17 blocks
==26082== suppressed: 0 bytes in 0 blocks
What do? This is homework stuff - can't ignore valgrind results.
Add a call to xmlCleanupCharEncodingHandlers() right before the call to xmlCleanupParser().
On my Mac OS 10.7.5 dev machine (libxml 20703), this fixes the reported "still reachable" leaks in libxml2.
By the way, ??? means that the debugging symbols for the object file are not available. It can be very helpful when tracking down memory leaks to have this information. The procedure for installing debugging information depends on the Linux distribution. On Ubuntu, for example, you can install the libxml2 debugging information with sudo apt-get install libxml2-dbg. See https://live.gnome.org/GettingTraces/DistroSpecificInstructions
This question is not a duplicate of many others, bekause I do use G_DEBUG=gc-friendly and G_SLICE=always-malloc
Here is the source code:
#include <glib.h>
int main (int argc, char *argv[])
{
GHashTable *ht;
ht=g_hash_table_new(g_str_hash,g_str_equal);
g_hash_table_insert(ht,"foo","bar");
g_hash_table_destroy(ht);
return 0;
}
And here is Valgrind's output on this code:
# G_DEBUG=gc-friendly G_SLICE=always-malloc valgrind --leak-check=full --show-reachable=yes ./test_vg
==1880== Memcheck, a memory error detector
==1880== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==1880== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info
==1880== Command: ./test_vg
==1880==
==1880==
==1880== HEAP SUMMARY:
==1880== in use at exit: 1,260 bytes in 3 blocks
==1880== total heap usage: 5 allocs, 2 frees, 1,524 bytes allocated
==1880==
==1880== 252 bytes in 1 blocks are still reachable in loss record 1 of 3
==1880== at 0x4A04A28: calloc (vg_replace_malloc.c:467)
==1880== by 0x35C8241707: g_malloc0 (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C8255742: ??? (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C825669D: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C822B1D2: g_hash_table_new_full (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x400671: main (in /home/data/test_vg)
==1880==
==1880== 504 bytes in 1 blocks are still reachable in loss record 2 of 3
==1880== at 0x4A04A28: calloc (vg_replace_malloc.c:467)
==1880== by 0x35C8241707: g_malloc0 (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C8255722: ??? (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C825669D: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C822B1D2: g_hash_table_new_full (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x400671: main (in /home/data/test_vg)
==1880==
==1880== 504 bytes in 1 blocks are still reachable in loss record 3 of 3
==1880== at 0x4A04A28: calloc (vg_replace_malloc.c:467)
==1880== by 0x35C8241707: g_malloc0 (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C825578B: ??? (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C825669D: g_slice_alloc (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x35C822B1D2: g_hash_table_new_full (in /lib64/libglib-2.0.so.0.2200.5)
==1880== by 0x400671: main (in /home/data/test_vg)
==1880==
==1880== LEAK SUMMARY:
==1880== definitely lost: 0 bytes in 0 blocks
==1880== indirectly lost: 0 bytes in 0 blocks
==1880== possibly lost: 0 bytes in 0 blocks
==1880== still reachable: 1,260 bytes in 3 blocks
==1880== suppressed: 0 bytes in 0 blocks
==1880==
==1880== For counts of detected and suppressed errors, rerun with: -v
==1880== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
Is it a memory-leak?
To answer your question: No, this is not a memory leak in the traditional sense. Your code is fine.
Even if you use G_DEBUG=gc-friendly and G_SLICE=always-malloc, GLib always leaves "still reachable" memory on exit. Don't use the --show-reachable=yes option, otherwise you'll always have a polluted Valgrind output when using GLib. However, be careful if you allocate memory to which you keep pointers in static or global variables ("still reachable" memory). In this case you might end up ignoring your own "real" leaks.
I have always had trouble with a lot of false and unreachable items when using Valgrind to check GLib 2 programs. In your case, the leaks seem to be from the creation of the hash table. I would create a second hash table and see if you get additional blocks (otherwise, it could be some internal initialization in GLib).
Some notes on using Valgrind with GLIB and GTK are at wiki.gnome.org.
Try passing --suppressions=/usr/share/glib-2.0/valgrind/glib.supp to valgrind. It suppresses the false positives from GLib.