C strings, strlen and Valgrind

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

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  #include  #include   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?

回答1:

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.



回答2:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!