I am currently looking into a C program to debug where Valgrind was reporting errors.
I've stripped out some of the code into a small project to test where I think the problem is and I believe I've pretty much replicated the problem.
Below is my main function
int main(int argc, char** argv) {
FILE *csvFile = NULL;
csvFile = fopen("test.txt", "wb");
int arraySize = 10;
int i = 0;
targetsStruct *targets;
targetSummaryResultStruct *targetSummaryResult;
targets = malloc(arraySize + 10 * sizeof(targets));
targetSummaryResult = malloc(arraySize + 10 * sizeof(targetSummaryResultStruct));
for (i = 0; i < arraySize; i++)
{
asprintf(&targets[i].target, "TargetStruct: %i", i);
targets[i].rowID = i;
}
for (i = 0; i < arraySize; i++)
{
asprintf(&targetSummaryResult[i].target, "Target: %s", targets[i].target);
free(targets[i].target);
printf("%s\n", targetSummaryResult[i].target);
targetSummaryResult[i].callAttempts = i * 10;
fprintf(csvFile, "%s = %i\n", targetSummaryResult[i].target, targetSummaryResult[i].callAttempts);
free(targetSummaryResult[i].target);
}
fclose(csvFile);
printf("Structure completed");
free(targetSummaryResult);
free(targets);
return (EXIT_SUCCESS);
}
I'm malloc'ing the memory on purpose to say its arraySize + 10. The reason for this is the program I am trying to debug allocates a lot more array elements than are actually needed so I'm testing if this is a potential problem so although the array is 10 elements bigger I'm actually only filling 0 to the arraySize and the next 10 are left.
Below is how my structures are defined
typedef struct TargetSummaryResultStruct
{
char * target;
int callAttempts;
} targetSummaryResultStruct;
typedef struct TargetsStruct
{
char * target;
int rowID;
} targetsStruct;
Below is my valgrind report:
==10244== HEAP SUMMARY:
==10244== in use at exit: 0 bytes in 0 blocks
==10244== total heap usage: 43 allocs, 43 frees, 2,892 bytes allocated
==10244==
==10244== All heap blocks were freed -- no leaks are possible
==10244==
==10244== ERROR SUMMARY: 20 errors from 5 contexts (suppressed: 12 from 8)
==10244==
==10244== 4 errors in context 1 of 5:
==10244== Invalid read of size 4
==10244== at 0x8048619: main (main.c:48)
==10244== Address 0x40181e8 is 48 bytes inside a block of size 50 alloc'd
==10244== at 0x40072D5: malloc (vg_replace_malloc.c:291)
==10244== by 0x804856D: main (main.c:35)
==10244==
==10244==
==10244== 4 errors in context 2 of 5:
==10244== Invalid read of size 4
==10244== at 0x80485EC: main (main.c:47)
==10244== Address 0x40181e8 is 48 bytes inside a block of size 50 alloc'd
==10244== at 0x40072D5: malloc (vg_replace_malloc.c:291)
==10244== by 0x804856D: main (main.c:35)
==10244==
==10244==
==10244== 4 errors in context 3 of 5:
==10244== Invalid write of size 4
==10244== at 0x80485C2: main (main.c:41)
==10244== Address 0x40181ec is 2 bytes after a block of size 50 alloc'd
==10244== at 0x40072D5: malloc (vg_replace_malloc.c:291)
==10244== by 0x804856D: main (main.c:35)
==10244==
==10244==
==10244== 4 errors in context 4 of 5:
==10244== Invalid read of size 4
==10244== at 0xAF770B: vasprintf (in /lib/libc-2.12.so)
==10244== by 0xAD956A: asprintf (in /lib/libc-2.12.so)
==10244== by 0x80485B2: main (main.c:40)
==10244== Address 0x40181e8 is 48 bytes inside a block of size 50 alloc'd
==10244== at 0x40072D5: malloc (vg_replace_malloc.c:291)
==10244== by 0x804856D: main (main.c:35)
==10244==
==10244==
==10244== 4 errors in context 5 of 5:
==10244== Invalid write of size 4
==10244== at 0xAF76DD: vasprintf (in /lib/libc-2.12.so)
==10244== by 0xAD956A: asprintf (in /lib/libc-2.12.so)
==10244== by 0x80485B2: main (main.c:40)
==10244== Address 0x40181e8 is 48 bytes inside a block of size 50 alloc'd
==10244== at 0x40072D5: malloc (vg_replace_malloc.c:291)
==10244== by 0x804856D: main (main.c:35)
==10244==
--10244--
--10244-- used_suppression: 12 U1004-ARM-_dl_relocate_object /usr/local/lib/valgrind/default.supp:1391
==10244==
==10244== ERROR SUMMARY: 20 errors from 5 contexts (suppressed: 12 from 8)
I'm not sure how to fix these errors, my understanding of the invalid reads is that I'm trying to access some memory that may have already been free'd but part of the memory wasn't free'd for some reason.
I am new to C.
There is an arithmetic precedence mistake. * evaluated before +, therefore you get a memory block with wrong size. Also at first malloc, you are allocating memory to hold pointer of targetsStruct not the struct itself.
targets = malloc((arraySize + 10) * sizeof(targetsStruct)); //change targets to targetsStruct
targetSummaryResult = malloc((arraySize + 10) * sizeof(targetSummaryResultStruct));
I think what you meant to do in your malloc is
targets = malloc((arraySize + 10) * sizeof *targets);
and similarly for other malloc's.
The sizes you pass to malloc are incorrect because you're doing sizeof on the wrong thing. You're doing sizeof on the pointer, which will result into the size of the pointer, not the thing it points to. I have no idea why you're adding "arraySize" to the size you're allocating, but the mallocs should look like this:
targets = malloc(arraySize * sizeof *targets);
targetSummaryResult = malloc(arraySize * sizeof *targetSummaryResultStruct);
These messages indicate that you are accessing the memory past the allocated size.
You have allocated 50 bytes, then access the 4 bytes at offset 48, which includes bytes 48, 49 (legal), and 50, 51 (outside the allocation).
Later on, you access bytes 52, 53, 54, 55, all of which are outside, and valgrind tells you that there are 2 bytes in between the end of the allocation and the start of your access.
Related
This reads from an already existing text file and creates 6 outfiles of little snippets from the infile. It works as predicted, but upon running valgrind I get multiple errors. However, there is no memory leak:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char buffer[5];
FILE* infile = fopen("clams.txt", "r");
if (infile == NULL)
{
return 1;
}
for (int i = 0; i < 6; i++)
{
fread(buffer, sizeof(char), 5, infile);
char* filename = malloc(sizeof(char) * 4); //line 17
sprintf(filename,"%03i.txt", i);
printf("%c%c%c\n", filename[0], filename[1], filename[2]); //19
FILE* outfile = fopen(filename, "w"); //21
if (outfile == NULL)
{
return 2;
}
fwrite(buffer, sizeof(char), 5, outfile);
fclose(outfile);
free(filename);
}
fclose(infile);
}
Valgrind said:
==1042== Invalid write of size 1
==1042== at 0x4C762B4: _IO_default_xsputn (genops.c:394)
==1042== by 0x4C762B4: _IO_default_xsputn (genops.c:370)
==1042== by 0x4C5B165: __vfprintf_internal (vfprintf-internal.c:1719)
==1042== by 0x4C69278: __vsprintf_internal (iovsprintf.c:95)
==1042== by 0x4C46047: sprintf (sprintf.c:30)
==1042== by 0x401234: main (filename.c:18)
==1042== Address 0x4dd62a4 is 0 bytes after a block of size 4 alloc'd
==1042== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1042== by 0x401218: main (filename.c:17)
==1042==
==1042== Invalid write of size 1
==1042== at 0x4C6927E: __vsprintf_internal (iovsprintf.c:97)
==1042== by 0x4C46047: sprintf (sprintf.c:30)
==1042== by 0x401234: main (filename.c:18)
==1042== Address 0x4dd62a7 is 3 bytes after a block of size 4 alloc'd
==1042== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1042== by 0x401218: main (filename.c:17)
==1042==
000
==1042== Syscall param openat(filename) points to unaddressable byte(s)
==1042== at 0x4CF1EAB: open (open64.c:48)
==1042== by 0x4C74195: _IO_file_open (fileops.c:189)
==1042== by 0x4C74459: _IO_file_fopen##GLIBC_2.2.5 (fileops.c:281)
==1042== by 0x4C66B0D: __fopen_internal (iofopen.c:75)
==1042== by 0x4C66B0D: fopen##GLIBC_2.2.5 (iofopen.c:86)
==1042== by 0x401275: main (filename.c:21)
==1042== Address 0x4dd62a4 is 0 bytes after a block of size 4 alloc'd
==1042== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==1042== by 0x401218: main (filename.c:17)
==1042==
001
002
003
004
005
==1042==
==1042== HEAP SUMMARY:
==1042== in use at exit: 0 bytes in 0 blocks
==1042== total heap usage: 20 allocs, 20 frees, 32,000 bytes allocated
==1042==
==1042== All heap blocks were freed -- no leaks are possible
==1042==
==1042== For lists of detected and suppressed errors, rerun with: -s
==1042== ERROR SUMMARY: 30 errors from 3 contexts (suppressed: 0 from 0)
(filename.c is the name of my program)
The only way I've been able to eliminate the errors is by changing line 17 to allocate 8 or more bytes. Anything between 4 and 7 inclusive gives me errors. I am confused as to why this is, given each string of 3 chars and the \0 should only take 4 bytes to store.
If I kept malloc(4), should I be concerned about those errors? For a similar program that uses much more memory (e.g. images instead of text), can those errors eventually lead to a crash or segmentation fault?
The problem is clear by looking at the following two lines:
char* filename = malloc(sizeof(char) * 4); // 17
sprintf(filename, "%03i.txt", i); // 18
At line 17 you allocate 4 bytes, which is enough space for a string of 3 characters plus a terminator (\0). Then, right after that, you write into that string more than 3 characters: at least 4 just from .txt, and then some more due to the %03i.
You should instead allocate more space. A conservative estimate for the needed size of the string holding the file name would be 4 (.txt) + 3 (since i can assume values from 0 to 5 and is padded to 3 decimal digits) + 1 (\0 terminator), so a total of 8 bytes.
This is why changing that malloc(4) into a malloc(8) does not produce errors.
By the way, for such a small buffer, you can avoid complicating things with malloc/free and just declare it on the stack as a local variable:
char filename[8];
If I kept malloc(4), should I be concerned about those errors?
Yes, you're writing past the end of an allocated buffer, which is undefined behavior in C, which means your program can easily crash, segfault, or do worse things.
For a similar program that uses much more memory (e.g. images instead of text), can those errors eventually lead to a crash or segmentation fault?
Even for the small program you just provided those errors can result in a crash, so yes.
I'm working on a math library.
create_vector create a vector of dimension n: (v1, v2, v3, ..., vn)
delete_vector free the memory.
struct Vector
{
unsigned int dimension;
double *components;
};
typedef struct Vector *vector_t;
vector_t create_vector(const unsigned int dimension)
{
if(!dimension)
return NULL;
vector_t vector = (vector_t)malloc(sizeof(struct Vector));
vector->dimension = dimension;
vector->components = (double *)calloc(dimension, sizeof(double));
return vector;
}
void delete_vector(vector_t *vector)
{
if(*vector == NULL)
return;
free((*vector)->components);
free(*vector);
*vector = NULL;
}
Main file:
int main()
{
vector_t vector1 = create_vector(3);
delete_vector(&vector1);
}
In main file, I use this two functions, but valgrind gives me these warnings. There isn't any memory leaks. How can i solve?
==6906== Invalid write of size 4
==6906== at 0x108800: create_vector (in /home/mrcoder/Scrivania/GitHub/libmath/test/testvector)
==6906== by 0x10877E: main (in /home/mrcoder/Scrivania/GitHub/libmath/test/testvector)
==6906== Address 0x4b3702c is 0 bytes after a block of size 4 alloc'd
==6906== at 0x483021B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==6906== by 0x1087DC: create_vector (in /home/mrcoder/Scrivania/GitHub/libmath/test/testvector)
==6906== by 0x10877E: main (in /home/mrcoder/Scrivania/GitHub/libmath/test/testvector)
==6906==
==6906== Invalid read of size 4
==6906== at 0x10882B: delete_vector (in /home/mrcoder/Scrivania/GitHub/libmath/test/testvector)
==6906== by 0x108790: main (in /home/mrcoder/Scrivania/GitHub/libmath/test/testvector)
==6906== Address 0x4b3702c is 0 bytes after a block of size 4 alloc'd
==6906== at 0x483021B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==6906== by 0x1087DC: create_vector (in /home/mrcoder/Scrivania/GitHub/libmath/test/testvector)
==6906== by 0x10877E: main (in /home/mrcoder/Scrivania/GitHub/libmath/test/testvector)
==6906==
==6906==
==6906== HEAP SUMMARY:
==6906== in use at exit: 0 bytes in 0 blocks
==6906== total heap usage: 2 allocs, 2 frees, 28 bytes allocated
==6906==
==6906== All heap blocks were freed -- no leaks are possible
==6906==
==6906== For counts of detected and suppressed errors, rerun with: -v
==6906== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Are you sure you do not compiled with malloc(sizeof(vector_t)); rather than with malloc(sizeof(struct Vector)); ?
block of size 4 alloc'd indicates you malloc only 4 bytes being the size of a pointer if you have a 32b CPU, the size of the struct is minimum 8 bytes
You have vector_t typedef'd to be a struct Vector *, so sizeof(vector_t) effectively expands to sizeof(struct Vector *). All pointers are the same size, either 4 or 8 whenever working on modern hardware, so you're not really getting the size of the struct, but the size of a pointer to your struct.
Instead you should do malloc(sizeof(struct Vector)) to get enough space for your structure.
I should dynamically allocate an array of pointers to structure, passing from time to time parameters for a single structure.
sorry if I can not explain, here is the code
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
typedef struct _DROP_DOWN_MENU_LABELS
{
char *title;
char **items;
} MenuLabels;
MenuLabels ** ml_init(void)
{
MenuLabels **ml;
ml=(MenuLabels **)calloc(2,sizeof(MenuLabels*));
ml[1]=NULL;
return ml;
}
void addit(MenuLabels **mlabels, char *title, char *elems,...)
{
int j;
for (j=0; mlabels[j]!=NULL ; j++ );
printf("\n\nCHECK:MenuLabels has %d menu",j);
mlabels=(MenuLabels **)realloc(mlabels,(j+2)*sizeof(MenuLabels*));
mlabels[j]=(MenuLabels *)malloc(1*sizeof(MenuLabels));
mlabels[j+1]=NULL;
mlabels[j]->title=title;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int i=0;
char **mitems=NULL;
mitems=(char **)malloc(sizeof(char*));
mitems[i]=elems;
va_list argP;
va_start(argP, elems);
char *p;
for (i=1; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
mitems[i]=p;
}
if (!p)
{
mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
mitems[i]=NULL;
}
va_end(argP);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
mlabels[j]->items=mitems;
}
int main()
{
MenuLabels **ml;
ml=ml_init();
addit(ml,"FILE","new","open","save","backup","print","setup","exit",NULL);
addit(ml,"AFILE","Anew","Asave","Abackup","Aexit",NULL);
addit(ml,"BFILE","Bnew","Bopen","Bsave","Bprint","Bexit",NULL);
free(ml);
fprintf(stdout,"\n\033[1;91m***END***\033[0m\n");
return 0;
}
starting the program seems to be executed without errors:
CHECK:MenuLabels has 0 menu
CHECK:MenuLabels has 1 menu
CHECK:MenuLabels has 2 menu
***END***
Process returned 0 (0x0) execution time : 0.001 s
Press ENTER to continue.
but checking with valgrind:
==5572== Memcheck, a memory error detector
==5572== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5572== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==5572== Command: ./prove
==5572==
==5572== Invalid read of size 8
==5572== at 0x400812: addit (main.c:26)
==5572== by 0x400B27: main (main.c:75)
==5572== Address 0x5204040 is 0 bytes inside a block of size 16 free'd
==5572== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400855: addit (main.c:29)
==5572== by 0x400AF1: main (main.c:74)
==5572== Block was alloc'd at
==5572== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x40075C: ml_init (main.c:15)
==5572== by 0x400AB0: main (main.c:73)
==5572==
CHECK:MenuLabels has 0 menu
==5572== Invalid free() / delete / delete[] / realloc()
==5572== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400855: addit (main.c:29)
==5572== by 0x400B27: main (main.c:75)
==5572== Address 0x5204040 is 0 bytes inside a block of size 16 free'd
==5572== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400855: addit (main.c:29)
==5572== by 0x400AF1: main (main.c:74)
==5572== Block was alloc'd at
==5572== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x40075C: ml_init (main.c:15)
==5572== by 0x400AB0: main (main.c:73)
==5572==
==5572== Invalid write of size 8
==5572== at 0x400882: addit (main.c:31)
==5572== by 0x400B27: main (main.c:75)
==5572== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5572==
==5572==
==5572== Process terminating with default action of signal 11 (SIGSEGV)
==5572== Access not within mapped region at address 0x0
==5572== at 0x400882: addit (main.c:31)
==5572== by 0x400B27: main (main.c:75)
==5572== If you believe this happened as a result of a stack
==5572== overflow in your program's main thread (unlikely but
==5572== possible), you can try to increase the size of the
==5572== main thread stack using the --main-stacksize= flag.
==5572== The main thread stack size used in this run was 8388608.
CHECK:MenuLabels has 0 menu==5572==
==5572== HEAP SUMMARY:
==5572== in use at exit: 112 bytes in 4 blocks
==5572== total heap usage: 14 allocs, 10 frees, 1,392 bytes allocated
==5572==
==5572== 16 bytes in 1 blocks are definitely lost in loss record 2 of 4
==5572== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400881: addit (main.c:31)
==5572== by 0x400B27: main (main.c:75)
==5572==
==5572== 96 (16 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
==5572== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400855: addit (main.c:29)
==5572== by 0x400AF1: main (main.c:74)
==5572==
==5572== LEAK SUMMARY:
==5572== definitely lost: 32 bytes in 2 blocks
==5572== indirectly lost: 80 bytes in 2 blocks
==5572== possibly lost: 0 bytes in 0 blocks
==5572== still reachable: 0 bytes in 0 blocks
==5572== suppressed: 0 bytes in 0 blocks
==5572==
==5572== For counts of detected and suppressed errors, rerun with: -v
==5572== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
./run_valgrind: riga 4: 5572 Errore di segmentazione (core dump creato) valgrind --leak-check=full --track-origins=yes --tool=memcheck ./prove
and in fact if I try to extract any value from ml at the end (eg ml[n]-> title) it goes into segmentation fault
what am I doing wrong? thank you all in advance
Here's one problem:
char **mitems;
// ... assuming there's a mitems = malloc(...) or similar here...
mlabels[j]->items=mitems;
free(mitems);
Here you have a a pointer, you make it point to some memory you allocate, you copy the pointer (so you have two pointers pointing to the same memory) and then you free the memory that both pointers are pointing to.
The free call makes not only mitems invalid, but also mlabels[j]->items.
I solved ... here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
typedef struct s_drop_down_menu_labels
{
char *title;
char **items;
} MenuLabels;
MenuLabels ** ml_init(void)
{
MenuLabels **ml;
ml=(MenuLabels **)calloc(2,sizeof(MenuLabels*));
ml[1]=NULL;
return ml;
}
void addit(MenuLabels ***mlabels, char *title, char *elems,...)
{
int j;
for (j=0; (*mlabels)[j]!=NULL ; j++ );
printf("\n\nCHECK:MenuLabels has %d menu",j);
*mlabels=(MenuLabels **)realloc(*mlabels,(j+2)*sizeof(MenuLabels*));
(*mlabels)[j]=(MenuLabels *)malloc(1*sizeof(MenuLabels));
(*mlabels)[j+1]=NULL;
(*mlabels)[j]->title=title;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int i=0;
char **mitems=NULL;
mitems=(char **)malloc(sizeof(char*));
mitems[i]=elems;
va_list argP;
va_start(argP, elems);
char *p;
for (i=1; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
mitems[i]=p;
}
if (!p)
{
mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
mitems[i]=NULL;
}
va_end(argP);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
(*mlabels)[j]->items=mitems;
free(mitems);
}
int main()
{
MenuLabels **ml;
ml=ml_init();
addit(&ml,"FILE","new","open","save","backup","print","setup","exit",NULL);
addit(&ml,"AFILE","Anew","Asave","Abackup","Aexit",NULL);
addit(&ml,"BFILE","Bnew","Bopen","Bsave","Bprint","Bexit",NULL);
addit(&ml,"CFILE","Cnew","Copen","Csave","Cbackup","Cprint","Csetup","Cexit",NULL);
addit(&ml,"DFILE","Dnew","Dsave","Dbackup","Dexit",NULL);
addit(&ml,"EFILE","Enew","Eopen","Esave","Eprint","Eexit",NULL);
printf("\n**********CHECK: %s",ml[3]->title);
for (int i=0;ml[i]!=NULL ;i++ )
free(ml[i]);
fprintf(stdout,"\n\033[1;91m***END***\033[0m\n");
return 0;
}
#Some_programmer_dude, if not free mitems then there will be no more accessible memory allocated ...thank you all
I would like to implement an application which is in charge of running several tasks in parallel.
Before adding real tasks, I tried to set the base but the program returns various error when executing by valgrind.
==4827== Thread 3:
==4827== Invalid free() / delete / delete[] / realloc()
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Address 0x5420070 is 48 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
==4827== Thread 1:
==4827== Invalid read of size 8
==4827== at 0x400CD3: main (in /home/test)
==4827== Address 0x5420068 is 40 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
==4827== Invalid read of size 8
==4827== at 0x400CFF: main (in /home/test)
==4827== Address 0x5420068 is 40 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
==4827== Invalid read of size 8
==4827== at 0x400D30: main (in /home/test)
==4827== Address 0x5420060 is 32 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
tstop
==4827== Invalid write of size 8
==4827== at 0x400D5B: main (in /home/test)
==4827== Address 0x5420068 is 40 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
tstop
==4827== Invalid free() / delete / delete[] / realloc()
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400D8C: main (in /home/test)
==4827== Address 0x5420040 is 0 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
==4827==
==4827== HEAP SUMMARY:
==4827== in use at exit: 1,614 bytes in 4 blocks
==4827== total heap usage: 9 allocs, 7 frees, 3,334 bytes allocated
==4827==
==4827== LEAK SUMMARY:
==4827== definitely lost: 0 bytes in 0 blocks
==4827== indirectly lost: 0 bytes in 0 blocks
==4827== possibly lost: 0 bytes in 0 blocks
==4827== still reachable: 1,614 bytes in 4 blocks
==4827== suppressed: 0 bytes in 0 blocks
I guess these errors are related to memory accessing already freed and invalid free().
However, I can not really understand how and why they occur.
typedef int (*init)();
typedef int (*launch)();
typedef int (*stop)();
typedef struct stTask stTask_t;
typedef struct stEngine stEngine_t;
struct stTask
{
char name[10];
init initTask;
launch launchTask;
stop stopTask;
pthread_t tId;
};
struct stEngine
{
int16_t NbTasks;
stTask_t* TaskThread;
};
static void sig_handler(int signo);
static int tinit(void);
static int tlaunch(void);
static int tstop(void);
static void* my_handler(void* params);
stTask_t array[] =
{
{"TEST", (init)tinit, (launch)tlaunch, (stop)tstop, 0},
{"TEST2", (init)tinit, (launch)tlaunch, (stop)tstop, 0}
};
int exitReq;
stEngine_t engine;
int main (int argc, char *argv[])
{
struct sigaction action;
int i;
exitReq = 0;
memset(&engine, 0, sizeof(stEngine_t));
engine.NbTasks = 2;
memset(&action, '\0', sizeof(action));
action.sa_handler = &sig_handler;
sigfillset(&action.sa_mask);
action.sa_flags = 0;
if ((sigaction(SIGTERM, &action, NULL) != 0) || (sigaction(SIGINT, &action, NULL) != 0)) {
exit(EXIT_FAILURE);
}
engine.TaskThread = malloc(engine.NbTasks * sizeof(stTask_t));
for (i = 0; i < engine.NbTasks; i++) {
engine.TaskThread[i] = array[i];
engine.TaskThread[i].initTask();
pthread_create(&engine.TaskThread[i].tId, NULL, my_handler, (void *) &engine.TaskThread[i]);
}
while (!exitReq) {
//... do stuff
sched_yield();
}
for (i = 0; i < engine.NbTasks; i++) {
(void)pthread_cancel(engine.TaskThread[i].tId);
pthread_join(engine.TaskThread[i].tId, NULL);
engine.TaskThread[i].stopTask();
engine.TaskThread[i].tId = 0;
}
free(engine.TaskThread);
memset(&engine, 0, sizeof(stEngine_t));
return 0;
}
static void sig_handler(int signo)
{
if (signo == SIGINT || signo == SIGTERM) {
exitReq = 1;
}
}
static void* my_handler(void* params)
{
stTask_t* ptask = (stTask_t*) params;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
while (!exitReq) {
ptask->launchTask();
pthread_testcancel();
}
free(ptask);
pthread_exit(NULL);
}
static int tinit(void)
{
fprintf(stdout, "%s\n", __func__);
return 0;
}
static int tlaunch(void)
{
fprintf(stdout, "%s\n", __func__);
return 0;
}
static int tstop(void)
{
fprintf(stdout, "%s\n", __func__);
return 0;
}
By adding a comment into the handling function: I got no error but several bytes are still allocated when the program is manually stopped.
//free(ptask);
I get no error but several bytes are still allocated when the program is manually stopped.
As required I pass the struc's address as last parameter of pthread_create, but I probably misunderstand something about the memory
==6017== HEAP SUMMARY:
==6017== in use at exit: 1,614 bytes in 4 blocks
==6017== total heap usage: 9 allocs, 5 frees, 3,334 bytes allocated
==6017==
==6017== LEAK SUMMARY:
==6017== definitely lost: 0 bytes in 0 blocks
==6017== indirectly lost: 0 bytes in 0 blocks
==6017== possibly lost: 0 bytes in 0 blocks
==6017== still reachable: 1,614 bytes in 4 blocks
==6017== suppressed: 0 bytes in 0 blocks
Could someone explain me why, in both cases, memory is not freed correctly ?
I want to read in from the arguments a file with a name of format filename.in and output a file with the exact same filename but with .out extension instead of .in (filename.out). The key is that filename can be anything.
This code compiles correctly and does the job I want, but when I run it with valgrind I get a bunch of errors. Can anyone tell me what's causing the errors?
int main(int argc, char * argv[])
{
int i, dotIndex;
char extOut[] = ".out";
char *filenameIn, *filenameOut, *aux;
FILE *fpIn, *fpOut;
filenameIn = argv[1];
aux = strchr(filenameIn, '.');
dotIndex = aux - filenameIn;
aux = (char *)malloc((strlen(filenameIn) - 1)*sizeof(char));
for(i = 0; i < dotIndex; i++)
aux[i] = filenameIn[i];
filenameOut = (char *)malloc((strlen(aux) + 5)*sizeof(char));
strcat(aux, extOut);
strcpy(filenameOut, aux);
/* open input file */
fpIn = fopen(filenameIn,"r");
if(fpIn == NULL) {
printf("Open error of input file\n");
exit(2);
}
/* open output file */
fpOut = fopen(filenameOut,"w");
if(fpOut == NULL) {
printf("Open error of output file\n");
exit(3);
}
fclose(fpOut);
fclose(fpIn);
free(aux);
free(filenameOut);
exit(0);
}
The valgrind report:
Command: ./doorsmaze text.in
==3493==
==3493== Invalid write of size 1
==3493== at 0x402C36B: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487AB: main (main.c:64)
==3493== Address 0x41ef02e is 0 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493== Invalid write of size 1
==3493== at 0x402C390: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487AB: main (main.c:64)
==3493== Address 0x41ef030 is 2 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493== Invalid read of size 1
==3493== at 0x402C6C5: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487BF: main (main.c:65)
==3493== Address 0x41ef02e is 0 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493==
==3493== HEAP SUMMARY:
==3493== in use at exit: 0 bytes in 0 blocks
==3493== total heap usage: 4 allocs, 4 frees, 719 bytes allocated
==3493==
==3493== All heap blocks were freed -- no leaks are possible
==3493== Command: ./doorsmaze text.in
==3493==
==3493== Invalid write of size 1
==3493== at 0x402C36B: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487AB: main (main.c:64)
==3493== Address 0x41ef02e is 0 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493== Invalid write of size 1
==3493== at 0x402C390: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487AB: main (main.c:64)
==3493== Address 0x41ef030 is 2 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493== Invalid read of size 1
==3493== at 0x402C6C5: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487BF: main (main.c:65)
==3493== Address 0x41ef02e is 0 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493==
==3493== HEAP SUMMARY:
==3493== in use at exit: 0 bytes in 0 blocks
==3493== total heap usage: 4 allocs, 4 frees, 719 bytes allocated
==3493==
==3493== All heap blocks were freed -- no leaks are possible
==3493==
==3493== For counts of detected and suppressed errors, rerun with: -v
==3493== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 0 from 0)
==3493== For counts of detected and suppressed errors, rerun with: -v
==3493== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 0 from 0)
You have some issues in your code
You might not get the last . in the filename
aux = strchr(filenameIn, '.');
better use strrchr. You should also check for NULL, just in case the filename doesn't include an extension.
You allocate memory large enough to hold filename.in (excluding the nul byte)
aux = (char *)malloc((strlen(filenameIn) - 1)*sizeof(char));
You do your own version of strncpy(aux, filenameIn, dotIndex)
for(i = 0; i < dotIndex; i++)
aux[i] = filenameIn[i];`
You write beyond the allocated buffer, because you miss the space for the last character plus the nul byte
strcat(aux, extOut);
To fix this, you must allocate enough memory, which is the length of filename.in plus 1 char ("out" is one longer than "in") plus nul byte
aux = (char *)malloc((strlen(filenameIn) + 2)*sizeof(char));