2014-09-12 15 views
6

strlen restituisce il numero di caratteri che precedono il carattere null terminante. Un'implementazione di strlen potrebbe assomigliare a questo:Strlen su una stringa con valori non inizializzati con comportamento non definito?

size_t strlen(const char * str) 
{ 
    const char *s; 
    for (s = str; *s; ++s) {} 
    return(s - str); 
} 

Questa particolare implementazione dereferenzia s, dove s possono contenere valori indeterminati. E 'equivalente a questo:

int a; 
int* p = &a; 
*p; 

Così, per esempio, se si dovesse fare questo (che causa strlen per dare un'uscita errata):

char buffer[10]; 
buffer[9] = '\0'; 
strlen(buffer); 

E' un comportamento indefinito?

+1

@ user2864740 sei sicuro che la stringa * deve * contenere un valore? Non è permesso a C di schiantarsi allegramente in una lettura prima di scrivere? – kay

risposta

2

La chiamata alla funzione standard strlen causa un comportamento non definito. DR 451 chiarisce questo:

funzioni di libreria esporranno comportamento non definito quando viene utilizzato su valori indeterminati

Per una discussione più approfondita see this thread.

+0

Il mio commento qui sotto si riferisce all'implementazione del poster di una funzione strlen. Concorda sul fatto che la libreria standard ha altri vincoli o libertà. Il buffer –

+0

[9] è piuttosto determinato ... – Basilevs

+0

@ KC-NH ha aggiornato il mio post per chiarire che sto parlando della funzione standard 'strlen', non della pseudo-implementazione di OP. –

1

No, non è un comportamento non definito. La tua funzione strlen si fermerà prima della fine del buffer. Se la funzione strlen fa riferimento al buffer [10], allora sì che non è definito.

Certamente sarà un comportamento imprevisto, poiché la maggior parte del buffer contiene dati casuali. "Non definito" è una parola speciale per le persone che scrivono standard linguistici. Significa che qualsiasi cosa potrebbe accadere, inclusi errori di memoria o l'uscita dal programma. Inaspettatamente, voglio dire che non è sicuro di quello che il programmatore voleva che succedesse. In alcune corse, il risultato di strlen potrebbe essere 3 o potrebbe essere 10.

0

Sì, è un comportamento non definito. Dal progetto C11 standard §J.2 "comportamento indefinito":

il comportamento è indefinito nei seguenti casi:

...

Il valore di un oggetto con durata di conservazione automatica viene utilizzato mentre è indeterminato.

+2

Questo codice non usa effettivamente i valori indeterminati ('buffer' non è indeterminato, ma' buffer [0] 'è). Tuttavia, 'strlen' usa i valori. Inoltre, questo allegato non è normativo (dovrebbe essere una sorta di indice per trovare vari casi di UB). Il testo normativo è più dettagliato e presenta alcune eccezioni per quando l'uso indeterminato non è UB. –

+1

L'oggetto non è solo "indeterminato" ma i valori sono solo "non specificati", quindi non può accadere nulla di male. –

2

Il comportamento della variante che si sta visualizzando è ben definito in queste circostanze.

  • I byte della matrice inizializzata avere tutti i valori indeterminati, ad eccezione dell'elemento 10 che si imposta 0.
  • L'accesso a un valore indeterminato sarebbe UB solo se l'indirizzo dell'oggetto sottostante non verrà mai preso o se il valore è una trap per il tipo corrispondente.
  • Poiché questa è una matrice e l'accesso agli elementi di matrice avviene tramite l'aritmetica del puntatore, il primo caso non è rilevante, qui.
  • È possibile accedere a qualsiasi valore char senza UB, le clausole sulle rappresentazioni di trap nello standard escludono esplicitamente tutti i tipi di carattere da quello.
  • Quindi i valori con cui si ha a che fare sono semplicemente "non specificati".
  • La lettura di valori non specificati può, secondo alcuni membri del comitato di standard C, dare risultati diversi ogni volta, ciò che alcuni chiamano uno stato "whobly" o così. Questa proprietà non è pertinente, qui, poiché la funzione legge un tale valore al massimo una volta.
  • Quindi il tuo accesso agli elementi dell'array ti dà un valore arbitrario ma valido char.
  • Si è sicuri che il ciclo for si arresta al più tardi nella posizione 9, in modo da non sovraccaricare l'array.

Quindi non possono accadere cose "cattive" oltre il visibile se si utilizza la versione specifica della funzione. Ma avere una chiamata di funzione che produce risultati non specificati è certamente nulla che tu voglia vedere nel codice reale. Qualcosa di simile qui porta a bug molto sottili, e dovresti evitarlo con tutti i mezzi.

Problemi correlati