2010-07-14 12 views
7

che sto cercando di capire perché Valgrind è sputando:C stringhe, strlen e Valgrind

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

ogni volta che sto applicando strlen su una stringa allocata dinamicamente?

Ecco una breve 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; 
} 

Ed ecco l'output risultato da 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) 

Qual è il modo corretto per evitare questi avvertimenti? Sono gli avvisi reali?

risposta

14

Questo è molto probabilmente legati a questo bugreport:

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

Come Paolo già suggerito, strlen() su piattaforme Intel utilizza opzionalmente ottimizzazione SSE per accelerare strlen e amici. Questa accelerazione comporta letture sicure dietro i blocchi assegnati, qualcosa di più vecchie versioni di valgrind non ha ancora capito. Quindi aggiorna il tuo valgrind e sarai OK.

+0

L'aggiornamento all'ultima versione SVN ha risolto il problema. Grazie per segnalare questo bug! :) – Lenain

+0

Ti ricordi quali versioni di valgrind è stata applicata a questo? – detly

+2

Questo è di nuovo un problema con recenti gcc e valgrind, e non è limitato solo a SSE, come puoi vedere qui: https://bugzilla.redhat.com/show_bug.cgi?id=678518 – Stef

4

La mia ipotesi è che l'implementazione di strlen sia stata ottimizzata in modo tale che legge 8 byte alla volta e testa il primo zero byte in qualsiasi punto della parola a 64 bit (probabilmente usando MMX/SSE). Ciò significa che per il tuo esempio di stringa da 12 byte sta leggendo 4 byte oltre la fine della stringa. È discutibile se questo sia un bug nell'implementazione strlen o meno. Penso che dovrai solo ignorarlo. O assicurati che le allocazioni di stringhe siano sempre multipli di 8 byte.

+3

No, non dovrebbe mai essere un problema con le letture SSE allineate. Se il primo byte è leggibile, anche l'ultimo è leggibile. Le letture allineate non possono estendersi ai limiti della pagina. È un insetto di valgrind - vedi la mia risposta. –

+0

@Luther: molte grazie per il chiarimento. –