2011-08-25 21 views
10

numCheck è un numero compreso tra 1-1000. Questo codice mi dà un segfault solo quando raccolgo i risultati di sprintf in charcheck. Se uso semplicemente sprintf senza utilizzare i risultati, non ottengo un errore di seg. Cosa sta succedendo qui?Errore di segmentazione Sprintf

char * numString; 
int charcheck = sprintf(numString, "%d", numCheck); 

risposta

7

È necessario fornire la propria memoria per sprintf. Inoltre, non usare sprintf, ma piuttosto snprintf:

char buf[1000] = {0}; 

snprintf(buf, 999, ....); 

In alternativa è possibile allocare memoria dinamicamente:

char * buf = new char[BUFSIZE]; 
snprintf(buf, BUFSIZE-1, ...); 
/* ... */ 
delete[] buf; 
+0

Esattamente perché funziona quando non raccolgo i risultati? – syl

+0

È un comportamento non definito. A volte il comportamento non definito si comporta esattamente come te lo aspetti, il che è probabilmente il caso peggiore. –

+1

Perché raccomandi 'snprintf' su' sprintf'? – Kevin

1

Il primo argomento sprintf deve puntare a un buffer valido. Hai un char* ma punta alla spazzatura.

modificare il codice per:

char numString[80] = { }; 
int charcheck = sprintf(numString, "%d", numCheck); 

In modo che numString in realtà punta a un buffer valida (di 80 caratteri in questo esempio, tutti gli elementi di cui vengono inizializzati a 0).

Sarebbe anche bene utilizzare snprintf in modo da poter passare la dimensione del buffer ad esso, che aiuterà a prevenire i buffer overflow:

const int bufsize = 80; 
char numString[bufsize] = { }; 
int charcheck = snprintf(numString, bufsize - 1, "%d", numCheck); 

noti che si sottrae uno dalla dimensione del buffer che si passa a snprintf perché non si desidera che utilizzi l'ultimo slot, che si desidera assicurarsi sia NULL per indicare la fine della stringa.

+0

C'è un modo per scoprire la dimensione del numero intero che sto passando nei caratteri in modo da poter allocare la quantità corretta di spazio invece di usare un valore arbitrario come 80? – syl

+0

@user probabilmente sarebbe più efficiente allocare semplicemente lo spazio extra (si può capire il numero massimo di caratteri che un numero può essere dal tipo in cui lo si sta memorizzando) perché il calcolo richiederebbe una cascata di 'if's. Calcoli solo il numero più grande il tuo numero è più piccolo di (ad esempio se è inferiore a 10 (ma sempre '> 0', attenzione) è 1 cifra, se è inferiore a 100 è di 2 cifre, ecc.). Ma allocare lo spazio nello stack richiede un tempo costante (e una costante molto piccola), quindi se non si fa qualcosa come 'char numString [9999999999999]' si dovrebbe andare bene –

0

è necessario allocare spazio per il risultato, come

char numString[50]; 
int charcheck = sprintf(numString, "%d", numCheck); 

Nel tuo caso il funzionamento interal di sprintf stanno cercando di riferimento null, che è il valore predefinito per un puntatore nel tuo caso.

1

Il puntatore indicato come primo parametro su sprintf punta a una posizione di memoria in cui sprintf dovrebbe scrivere la stringa formattata.

In questo caso non è stato inizializzato numString in modo che punti ad alcuna memoria allocata per la stringa formattata. Poiché numString non è inizializzato, potrebbe puntare ovunque, e nel tuo caso provare a scrivere l'output formattato in quella posizione provoca un errore di segmentazione.

0

La cosa più semplice da fare è quello di utilizzare un array come sopra, per esempio,

char numString[80] = { }; 

suggerito da Seth, Gesù e Kerrek.

Penso che l'ultima risposta di sth sia una buona spiegazione: "il primo parametro di sprintf dovrebbe puntare a una posizione di memoria in cui sprintf dovrebbe scrivere la stringa formattata." Quindi, oltre ad utilizzare un array di caratteri, che costringerebbero la dotazione di memoria per la stringa, è anche possibile utilizzare questo:

char *numstring = (char*) malloc(80); 

Questo dovrebbe permettere di liberare la memoria allocata in modo esplicito quando non è più necessario.