I have a function which prints the whole content of the file and the function seems to work fine, but valgring complains about Conditional jump or move depends on uninitialised value(s) and Uninitialised value was created by a heap allocation:
==7876== Memcheck, a memory error detector ==7876== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==7876== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==7876== Command: ./program ==7876== ==7876== Conditional jump or move depends on uninitialised value(s) ==7876== at 0x4E864B2: vfprintf (vfprintf.c:1642) ==7876== by 0x4E8CC38: printf (printf.c:33) ==7876== by 0x40074C: main (program.c:45) ==7876== Uninitialised value was created by a heap allocation ==7876== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7876== by 0x4008A7: printFile (program.c:23) ==7876== by 0x40073A: main (program.c:43) ==7876== The world is not enought and michi is the only one who's not agree. ==7876== ==7876== HEAP SUMMARY: ==7876== in use at exit: 0 bytes in 0 blocks ==7876== total heap usage: 2 allocs, 2 frees, 621 bytes allocated ==7876== ==7876== All heap blocks were freed -- no leaks are possible ==7876== ==7876== For counts of detected and suppressed errors, rerun with: -v ==7876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Here is the program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *printFile(char *fileName){
size_t length=0,size=0;
char *buffer;
FILE *file;
file = fopen (fileName , "r" );
if (file==NULL){
printf("\n");
printf("\tThe file %s does not Exists\n", fileName);
exit(1);
}
fseek (file , 0 , SEEK_END);
length = (size_t)ftell (file);
fseek (file , 0 , SEEK_SET);
buffer = malloc(length+1);
if (!buffer){
fputs ("Memory error",stderr);
exit (2);
}
size = fread (buffer,1,length+1,file);
if (size != length){
fputs ("Reading error",stderr);
exit(3);
}
fclose (file);
return buffer;
}
int main (void) {
char *fileName = "test.txt";
char *fileContent = printFile(fileName);
printf("%s",fileContent);
free(fileContent);
return 0;
}
A quick fix is to use calloc instead of malloc, because it zeros the returned bytes So I replaced:
buffer = malloc(length+1);
with:
buffer = calloc(length,sizeof(char*));
And valgrind doesn't complain:
==7897== Memcheck, a memory error detector ==7897== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==7897== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==7897== Command: ./program ==7897== The world is not enought and michi is the only one who's not agree. ==7897== ==7897== HEAP SUMMARY: ==7897== in use at exit: 0 bytes in 0 blocks ==7897== total heap usage: 2 allocs, 2 frees, 1,096 bytes allocated ==7897== ==7897== All heap blocks were freed -- no leaks are possible ==7897== ==7897== For counts of detected and suppressed errors, rerun with: -v ==7897== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
My question is, why does malloc produce that error and how to avoid calloc. Do I have some codding problem here or is just malloc? . . EDIT: if I change:
size = fread (buffer,1,length+1,file);
with:
size = fread (buffer,1,length,file);
I get:
==7985== Memcheck, a memory error detector ==7985== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==7985== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==7985== Command: ./program ==7985== ==7985== Invalid read of size 1 ==7985== at 0x4E864B2: vfprintf (vfprintf.c:1642) ==7985== by 0x4E8CC38: printf (printf.c:33) ==7985== by 0x40074C: main (program.c:44) ==7985== Address 0x52022f4 is 0 bytes after a block of size 68 alloc'd ==7985== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7985== by 0x4008A6: printFile (program.c:22) ==7985== by 0x40073A: main (program.c:42) ==7985== The world is not enought and michi is the only one who's not agree. ==7985== ==7985== HEAP SUMMARY: ==7985== in use at exit: 0 bytes in 0 blocks ==7985== total heap usage: 2 allocs, 2 frees, 620 bytes allocated ==7985== ==7985== All heap blocks were freed -- no leaks are possible ==7985== ==7985== For counts of detected and suppressed errors, rerun with: -v ==7985== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Your string must be NUL-terminated. Without it, the program has undefined behaviour, which valgrind rightfully reports.
The easiest way to NUL-terminate the string is:
size = fread (buffer,1,length,file); /* no need to specify useless extra char */
/* it will never be read */
... /* check for errors here */
buffer[length] = '\0'; /* <--- null termination */
calloc
fills the entire buffer with NUL characters, but it's a waste of cycles. You only need one.