2010-07-14 14 views
7

que estoy tratando de entender por qué Valgrind es escupir a cabo:cadenas de C, strlen y Valgrind

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

cuando estoy aplicando strlen en una cadena asignada dinámicamente?

He aquí una breve caso_prueba:

#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; 
} 

Y aquí es el resultado emitido desde Valgrind:

[email protected]:~/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) 

Cuál es la forma correcta para evitar estas advertencias? ¿Son reales advertencias?

Respuesta

14

Esto es más probable en relación a este informe de error:

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

Como ya se ha sugerido Paul, strlen() en las plataformas Intel utiliza de forma opcional SSE optimización para acelerar amigos y strlen. Esta aceleración implica lecturas seguras detrás de los bloques asignados, algo que versiones anteriores de valgrind aún no entendían. Así que actualice su valgrind y estará bien.

+0

Actualizar a la última versión de SVN corrigió el problema. ¡Gracias por señalar este error! :) – Lenain

+0

¿Recuerdas a qué versiones de valgrind esto se aplica? – detly

+2

Esto es nuevamente un problema con ggr y valgrind recientes, y no está limitado solo a SSE, como puede ver aquí: https://bugzilla.redhat.com/show_bug.cgi?id=678518 – Stef

4

Supongo que su implementación strlen ha sido optimizada de modo que lee 8 bytes a la vez y prueba el primer byte cero en cualquier parte de la palabra de 64 bits (probablemente usando MMX/SSE). Esto significa que para su ejemplo de cadena de 12 bytes está leyendo 4 bytes más allá del final de la cadena. Es discutible si esto es un error en la implementación strlen o no. Creo que solo tendrás que ignorarlo. O asegúrese de que las asignaciones de cadenas siempre sean múltiplos de 8 bytes.

+3

No, nunca debería ser un problema con las lecturas de SSE alineadas. Si el primer byte es legible, el último es legible también. Las lecturas alineadas no pueden abarcar los límites de la página. Es un error valgrind - ver mi respuesta. –

+0

@Luther: muchas gracias por la aclaración. –