I'm having a bit of an issue trying to understand why valgrind is telling me I am going out of bounds in a char *array.
Whenever I try to iterate the array backwards starting from before the nul byte. It throws me the error that I am accessing memory I am not supposed to.
This is my first function:
char *ReadLineFile(FILE *infile) {
int initSize = 16;
char *string = NULL;
string = malloc(sizeof(char) * initSize);
if(string == NULL){
exit(-1);
}
char val;
int valSize = 0;
while((val = fgetc(infile)) != EOF){
if(val == '\n'){
break;
}
if(valSize == initSize){
initSize *= 2;
string = realloc(string, initSize * sizeof(char));
}
string[valSize++] = val;
}
if(valSize == initSize){
initSize++;
string = realloc(string, initSize * sizeof(char));
}
string[valSize++] = '\0';
return trimString(string);
}
This is my second function:
char *trimString(char *string) {
int start = 0;
int end = strlen(string);
while(string[start] == ' '){start++;}
while(string[end-2] == ' '){end--;} // the [end-2] causes the error in valgrind
int trimLen = end - start;
char *trimmedStr = malloc(sizeof(char) * (trimLen + 1));
if(trimmedStr == NULL){
exit(-1);
}
int i = 0;
while(start != end){
trimmedStr[i] = string[start];
i++; start++;
}
trimmedStr[i] = '\0';
free(string);
return trimmedStr;
}
Valgrind error:
==3809== Invalid read of size 1
==3809== at 0x1090D5: trimString (myio.c:129)
==3809== by 0x109080: ReadLineFile(myio.c:120)
==3809== by 0x108C54: main (driver2.c:29)
==3809== Address 0x522e03e is 2 bytes before a block of size 16 alloc'd
==3809== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload/memcheck-amd64-linux.so)
==3809== by 0x108F91: ReadLineFile(myio.c:90)
==3809== by 0x108C54: main (driver2.c:29)
I expected valgrind to come out with not errors since I allocated enough memory in the strings but instead is telling me that I'm trying to access memory I'm not supposed to when I try to iterate the array backwards. I wish to understand what's causing this since I've spend multiple hours trying to figure out this error. Thanks!
What if the line is just spaces, or an empty line?
In that case while(string[end-2] == ' '){end--;}
might reach the beginning of the line and continue walking "backwards".
Consider testing the limits of the line / string. Also, why -2
? why not -1
?i.e.:
while(end > start && string[end - 1] == ' ') --end;
This approach will protect you from "walking" too far back.
Side-Note:
The EOF
marker isn't a valid byte (it isn't in the 0-255 value range). If it were, it might be a valid value in the middle of a file.
For this reason, EOF can't be contained in a char
you can't test if a char
contains an EOF. Use int val
instead of char val
.