Я пытаюсь понять, почему Valgrind выкладывает:
==3409== Invalid read of size 8
==3409== at 0x4EA3B92: __GI_strlen (strlen.S:31)
каждый раз, когда я применяю strlen на динамично выделенную строку?
Вот короткий тестовый сценарий:
#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;
}
И вот вывод результата от 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)
Что корректный путь состоит в том, чтобы избежать этих предупреждений? Они - реальные предупреждения?
Скорее всего, это связано с этим сообщением об ошибке:
https://bugzilla.redhat.com/show_bug.cgi?id=518247
Как уже предположил Пол, strlen () на платформах Intel может дополнительно использовать оптимизацию SSE. для ускорения strlen и друзья. Это ускорение включает безопасное чтение за выделенными блоками, чего еще не понимали старые версии valgrind. Так что обновите свой valgrind, и все будет в порядке.
Я предполагаю, что ваша реализация strlen оптимизирована таким образом, что она читает 8 байтов за раз и тестирует первый нулевой байт в любом месте 64-битного слова (возможно, с использованием MMX / SSE). Это означает, что для вашего примера 12-байтовой строки он читает 4 байта после конца строки. Спорный вопрос, является ли это ошибкой в реализации strlen или нет. Я думаю, тебе просто придется проигнорировать это. Или убедитесь, что ваши строковые выделения всегда кратны 8 байтам.