Search code examples
cvalgrind

Valgrind : Invalid read of size 1


I have the following code and I can't figure out why I'm getting this error from valgrind (for context I'm trying to copy a text from file into a string variable)

int main(int argc, char **argv)
{
  FILE *fp;
  int f_size;
  char *string;

  fp = fopen("./src/input.txt", "rw+");
  if (fp == NULL)
  {
    printf("Error!");
    exit(1);
  }

  fseek(fp, 0, SEEK_END);
  f_size = ftell(fp);
  fseek(fp, 0, SEEK_SET);

  string = (char *)malloc(sizeof(char) * f_size);
  fread(string, sizeof(char), f_size, fp);
  printf("\n%s\n", string);
  
  free(string);
  fclose(fp);
  return 0;
} /* main */

I get the following error by the printf seems like

==19085== Memcheck, a memory error detector
==19085== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==19085== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==19085== Command: ./build/find_word
==19085== 

==19085== Invalid read of size 1
==19085==    at 0x483EF54: strlen (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==19085==    by 0x48CEE94: __vfprintf_internal (vfprintf-internal.c:1688)
==19085==    by 0x48B7EBE: printf (printf.c:33)
==19085==    by 0x10958C: main (main.c:44)
==19085==  Address 0x4a4932e is 0 bytes after a block of size 142 alloc'd
==19085==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==19085==    by 0x109555: main (main.c:42)
==19085== 
text from file
==19085== 
==19085== HEAP SUMMARY:
==19085==     in use at exit: 0 bytes in 0 blocks
==19085==   total heap usage: 4 allocs, 4 frees, 5,734 bytes allocated
==19085== 
==19085== All heap blocks were freed -- no leaks are possible
==19085== 
==19085== For lists of detected and suppressed errors, rerun with: -s
==19085== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Solution

  • The buffer you allocated is large enough to hold the characters read from the file, but nothing else. Assuming the file contains only text, that means string is not actually a string because there is no terminating null byte. So when you pass it to printf, it reads past the end of the allocated memory, which is what valgrind is telling you.

    You need to add 1 to the amount of memory allocated and manually write a 0 to that last byte after filling the buffer to have a proper string.

    string = malloc(sizeof(char) * f_size + 1);
    fread(string, sizeof(char), f_size, fp);
    string[f_size] = 0;