views:

80

answers:

2

Hi everybody,

I'm trying to understand why Valgrind is spitting out :

==3409== Invalid read of size 8
==3409==    at 0x4EA3B92: __GI_strlen (strlen.S:31)

whenever I'm applying strlen on a dynamically allocated string?

Here is a short testcase :

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

int main() {

  char *hello = "Hello World";
  char *hello2;

  /* Step 1 */
  printf("Step 1\n");
  printf("strlen : %lu\n",(unsigned long)strlen(hello));

  /* Step 2 */
  hello2 = calloc(12,sizeof(char));
  hello2[0] = 'H';
  hello2[1] = 'e';
  hello2[2] = 'l';
  hello2[3] = 'l';
  hello2[4] = 'o';
  hello2[5] = ' ';
  hello2[6] = 'W';
  hello2[7] = 'o';
  hello2[8] = 'r';
  hello2[9] = 'l';
  hello2[10] = 'd';
  hello2[11] = 0;  

  printf("Step 2\n");
  printf("strlen : %lu\n",(unsigned long)strlen(hello2));
  free(hello2);

  return 0;
}

And here is the result output from Valgrind :

lenain@perseus:~/work/leaf$ valgrind ./leaf
==3409== Memcheck, a memory error detector
==3409== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3409== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info
==3409== Command: ./leaf
==3409== 
Step 1
strlen : 11
Step 2
==3409== Invalid read of size 8
==3409==    at 0x4EA3B92: __GI_strlen (strlen.S:31)
==3409==    by 0x40098A: main (in /home/lenain/work/leaf/leaf)
==3409==  Address 0x5189048 is 8 bytes inside a block of size 12 alloc'd
==3409==    at 0x4C234CB: calloc (vg_replace_malloc.c:418)
==3409==    by 0x4008F0: main (in /home/lenain/work/leaf/leaf)
==3409== 
strlen : 11
==3409== 
==3409== HEAP SUMMARY:
==3409==     in use at exit: 0 bytes in 0 blocks
==3409==   total heap usage: 1 allocs, 1 frees, 12 bytes allocated
==3409== 
==3409== All heap blocks were freed -- no leaks are possible
==3409== 
==3409== For counts of detected and suppressed errors, rerun with: -v
==3409== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)

What is the correct way to avoid these warnings? Are they real warnings?

+4  A: 

My guess is that your strlen implementation has been optimised such that it reads 8 bytes at a time and tests for the first zero byte anywhere in the 64 bit word (probably using MMX/SSE). This means that for your 12 byte string example it's reading 4 bytes beyond the end of the string. It's arguable as to whether this is a bug in the strlen implementation or not. I think you'll just have to ignore it. Or make sure your string allocations are always multiples of 8 bytes.

Paul R
No, should never be a problem with aligned SSE reads. If the first byte is readable, then the last is readable too. Aligned reads cannot span page boundaries. It's a valgrind bug - see my answer.
Luther Blissett
@Luther: many thanks for the clarification.
Paul R
+7  A: 

This is most likely related to this bugreport:

https://bugzilla.redhat.com/show_bug.cgi?id=518247

As Paul already suggested, strlen() on intel platforms optionally uses SSE optimization to speed up strlen and friends. This speed up involve safe reads behind the allocated blocks, something older versions of valgrind did not understand yet. So upgrade your valgrind and you will be OK.

Luther Blissett
Upgrade to last SVN version corrected the problem. Thanks to point this bug out! :)
Lenain