Search code examples
cmallocvalgrindreversememcheck

C - Valgrind detects an error in my reverse-string function


I wrote a small program that seems to work fine, but valgrind give me a weird error when I run memcheck. I need help in interpreting the error code :)

#include <stdio.h>
#include <stdlib.h>


int get_length(char* str){
   int i=0;
   char c = str[0];
   while(c!='\0'){
   i++;
   c=str[i]; 
   }
   return i;
}

char* rev(char* str){
   int length = get_length(str);
   char* x=malloc(length*sizeof(char));
   int i;
   length-=1;
   for(i=0; i<=length; i++){
      x[i]=str[length-i];
   }
   return x;
}

int main(){
   char* s=rev("roma");
   printf("%s\n",s);
   free(s);
}

valgrind output below:

Invalid read of size 1
==14727==    at 0x4C29724: __GI_strlen (mc_replace_strmem.c:405)
==14727==    by 0x4E9907A: puts (ioputs.c:37)
==14727==    by 0x400673: main (in /home/francesco80b/Scrivania/i_a/l-04/main.o)
==14727==  Address 0x51ba044 is 0 bytes after a block of size 4 alloc'd
==14727==    at 0x4C28D84: malloc (vg_replace_malloc.c:291)
==14727==    by 0x400601: rev (in /home/francesco80b/Scrivania/i_a/l-04/main.o)
==14727==    by 0x400663: main (in /home/francesco80b/Scrivania/i_a/l-04/main.o)
==14727== 
amor
==14727== 
==14727== HEAP SUMMARY:
==14727==     in use at exit: 0 bytes in 0 blocks
==14727==   total heap usage: 1 allocs, 1 frees, 4 bytes allocated
==14727== 
==14727== All heap blocks were freed -- no leaks are possible

I also noticed that, if I use calloc() instead of using malloc(), valgrind doesn't detects any errors at all.

NOTE: I wrote the get_length() function just for fun, lol


Solution

  • You allocated fewer characters than you need:

    char* x=malloc(length*sizeof(char));
    

    should be

    char* x=malloc(length+1);
    

    Multiplying by sizeof(char) is unnecessary, because the standard requires it to be 1. Adding 1 is required, because you need an extra character for the null terminator, which your function fails to add. That is why the invalid read happens when printf tries to print the string.

    To fix this problem, allocate length+1, and add x[length] = '\0'; before returning x from the function.