2012-04-10 2 views
8

Nel seguente:due casi durante il tentativo di stampare NULL, si lavora, altre segfaults

printf("Example%s\n",NULL); 
printf("%s\n",NULL); 

Ho l'output come:

Example(null) 
Segmentation Fault 

Quando ho provato backtrace in GDB si dimostra printf() è convertito in puts(). Ma non riesco a capire perché questo accada.

BTW Ho trovato l'articolo this ma non riesco ancora a dare un senso.

+0

' gcc' fa varie ottimizzazioni. Vedere la sezione 2.3 e 3.1 in particolare su http://www.ciselant.de/projects/gcc_printf/gcc_printf.html – FatalError

+1

Si veda anche questo rapporto sugli errori 'gcc' per ulteriori discussioni sul motivo per cui questo non è considerato un bug: http: //gcc.gnu. org/bugzilla/show_bug.cgi? id = 25609 – shf301

+0

Una domanda simile: [Non ottenere errori di segmentazione in C] (http://stackoverflow.com/questions/8861833/not-getting-segmentation-fault-in-c) –

risposta

15

La norma dice che passando un puntatore NULL come argomento di un printf con %s identificatore è un comportamento indefinito (vale a dire tutto può succedere), in modo da entrambi i comportamenti sono leciti.

Nel primo caso, la libreria standard (in particolare, il codice printf) ti sta facendo un favore stampando (null).

Nel secondo caso, l'ottimizzatore comprende che il tuo printf può essere sostituito da un puts (che è più efficiente) senza alcuna modifica al "comportamento osservabile" del programma, e quindi lo sostituisce. Ma, puts non contiene il codice di controllo NULL di printf e pertanto si verifica un errore di segmentazione.


  1. C99, §7.19.6.1, ¶8:

    l'argomento sarà un puntatore all'elemento iniziale di un array di tipo carattere.

    ¶9:

    Se uno degli argomenti non è del tipo corretto per la specifica di conversione corrispondente, il comportamento è indefinito.

    si rientra in quest'ultimo caso, a causa NULL non è "un puntatore al primo elemento di un array di tipo carattere.

+1

Esattamente; il secondo 'printf' stampa solo l'argomento dato seguito da una nuova riga, che è esattamente ciò che fa 'puts'; il primo, invece, fa cose un po 'più complicate. Comunque, questi sono dettagli specifici dell'implementazione: l'importante è che tu non debba passare 'NULL' come argomento per un' printf' con '% s', perché è un comportamento indefinito. –

+0

Grazie per il tuo aiuto :) – noMAD