Valgrind Invalid write and read of size 1 and bytes lost

Viewed 34

I was doing a split function with memory allocation. And I ran it through valgrind and came to a bunch of leaks and lost bytes.

Here's my function:

char **split(const char *str, char delim, int *n) {
  int count = 1;
  int len = strlen(str);
  char **words;
  for (int i = 0; i < len; i++) {
    if (str[i] == delim || str[i] == '\n' || str[i] == '\0')
      count++;
  }
  *n = count;
  words = (char **)malloc(count * sizeof *words);
  char arr[100];
  int j = 0, indeks = 0;
  for (int i = 0; i < len + 1; i++) {
    if (str[i] != delim && str[i] != '\n' && str[i] != '\0') {
      arr[j++] = str[i];
    } else {
      arr[j] = '\0';
      j = 0;
      words[indeks] = malloc(strlen(arr) * sizeof *words);
      words[indeks] = strcpy(words[indeks], arr);
      indeks++;
    }
  }

  words[indeks] = malloc(sizeof *words[indeks]);
  words[indeks][0] = '\0';
  return words;
} 

Here's my main:

int main() {
  int n = 0;
  char *str = "hello world !!!";
  char delim = ' ';
  printf("Input string: %s\n", str);
  printf("delimiter: %c\n", delim);

  char **words = split(str, delim, &n);
  printf("words:\n");
  for (int i = 0; i < n; i += 1) {
    printf("%s\n", words[i]);
  }
  free(words);
}

Memory leaks:

==12853== Invalid write of size 1
==12853==    at 0x4C34EAB: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12853==    by 0x108A49: split (naloga_3.h:28)
==12853==    by 0x108B4E: main (main.c:10)
==12853==  Address 0x52302f0 is 0 bytes after a block of size 0 alloc'd
==12853==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12853==    by 0x1089FE: split (naloga_3.h:27)
==12853==    by 0x108B4E: main (main.c:10)
==12853== 
==12853== Invalid write of size 8
==12853==    at 0x108A95: split (naloga_3.h:33)
==12853==    by 0x108B4E: main (main.c:10)
==12853==  Address 0x52300a8 is 0 bytes after a block of size 40 alloc'd
==12853==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12853==    by 0x108906: split (naloga_3.h:18)
==12853==    by 0x108B4E: main (main.c:10)
==12853== 
==12853== Invalid read of size 8
==12853==    at 0x108AB2: split (naloga_3.h:34)
==12853==    by 0x108B4E: main (main.c:10)
==12853==  Address 0x52300a8 is 0 bytes after a block of size 40 alloc'd
==12853==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12853==    by 0x108906: split (naloga_3.h:18)
==12853==    by 0x108B4E: main (main.c:10)
==12853== 
==12853== Invalid read of size 1
==12853==    at 0x4C34D32: __strlen_sse2 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12853==    by 0x4EBE981: puts (ioputs.c:35)
==12853==    by 0x108B86: main (main.c:13)
==12853==  Address 0x52302f0 is 0 bytes after a block of size 0 alloc'd
==12853==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12853==    by 0x1089FE: split (naloga_3.h:27)
==12853==    by 0x108B4E: main (main.c:10)
==12853== 
==12853== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==12853==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12853==    by 0x108A94: split (naloga_3.h:33)
==12853==    by 0x108B4E: main (main.c:10)
==12853== 
==12853== 232 bytes in 5 blocks are definitely lost in loss record 2 of 2
==12853==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12853==    by 0x1089FE: split (naloga_3.h:27)
==12853==    by 0x108B4E: main (main.c:10)
==12853== 

Can someone help me with the malloc function calls.

2 Answers

The function is wrong. For example in this statement

words[indeks] = malloc(strlen(arr) * sizeof *words);

you are allocating an array of pointers instead of an array of characters. You need to write

words[indeks] = malloc(strlen(arr) + 1 );

This assignment

words[indeks] = strcpy(words[indeks], arr);

does not make a great sense. It is enough to write

strcpy(words[indeks], arr);

And you need also to free all allocated arrays that store strings.

Pay attention to that the function will not correctly work when the source string contains adjacent spaces.

I would suggest making your code even simpler, and using strdup rather than malloc and strcpy. strdup will take care of of both allocating the right amount of memory and null terminating the resulting string.

When you've fixed your invalid memory accesses you can look at the leaks.

Related