2011-08-25 18 views
10

numCheck es el número entre 1-1000. Este código me da una segfault solo cuando colecciono los resultados de sprintf en charcheck. Si simplemente uso sprintf sin usar los resultados, no obtengo un fallo seg. ¿Que esta pasando aqui?Falla de segmentación de Sprintf

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

Respuesta

7

Debe proporcionar su propia memoria para sprintf. Además, no utilice sprintf, sino más bien snprintf:

char buf[1000] = {0}; 

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

alternativa, se puede asignar memoria dinámicamente:

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

¿Por qué funciona exactamente cuando no recopilo los resultados? – syl

+0

Es un comportamiento indefinido. A veces, el comportamiento indefinido se comporta exactamente como lo espera, lo que podría decirse que es el peor de los casos. –

+1

¿Por qué recomiendas 'snprintf' sobre' sprintf'? – Kevin

1

El primer argumento de sprintf debe apuntar a un tampón válido. Tienes un char* pero apunta a la basura.

cambiar el código para:

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

Para que numString realidad apunta a un tampón válido (de 80 caracteres en este ejemplo, todos los elementos de los cuales se inicializan a 0).

También sería bueno utilizar snprintf para que pueda pasar el tamaño de la memoria intermedia a la misma, lo que ayudará a evitar desbordamientos de búfer:

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

en cuenta que se resta uno del tamaño del búfer que se pasa a snprintf porque no desea que use la última ranura, que quiere asegurarse de que sea NULL para indicar el final de la cadena.

+0

¿Hay alguna manera de averiguar el tamaño del número entero que paso en caracteres para poder asignar la cantidad correcta de espacio en lugar de usar un valor arbitrario como 80? – syl

+0

@user probablemente sería más eficiente asignar el espacio extra (puede averiguar los caracteres máximos que un número puede ser por el tipo en que lo está almacenando) porque calcularlo requeriría una cascada de 'if's. Simplemente calcula cuál es el número más grande que su número es más pequeño que (por ejemplo, si es menor que 10 (pero siempre '> 0 ', téngalo en cuenta) es 1 dígito, si es más pequeño que 100 son 2 dígitos, etc.). Pero asignar espacio en la pila requiere tiempo constante (y una constante muy pequeña en eso) así que mientras no hagas algo como 'char numString [9999999999999]' deberías estar bien. –

0

es necesario asignar espacio para el resultado como

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

En su caso el funcionamiento de interal sprintf están tratando de hacer referencia a NULL que es el valor por defecto para un puntero en su caso.

1

Se espera que el puntero dado como primer parámetro a sprintf apunte a una ubicación de memoria donde sprintf debe escribir la cadena formateada.

En este caso, no inicializó numString para apuntar a la memoria que asignó para la cadena formateada. Como numString no se inicializa, puede apuntar a cualquier lugar, y en su caso intentar escribir la salida formateada en esa ubicación da como resultado un error de segmentación.

0

Lo más sencillo que hacer es utilizar una matriz que el anterior, por ejemplo,

char numString[80] = { }; 

sugeridos por Seth, Jesús y kerrek.

Creo que la última respuesta de sth es una buena explicación: "se espera que el primer parámetro para sprintf apunte a una ubicación de memoria donde sprintf debe escribir la cadena formateada". Así que aparte de usar una matriz de caracteres, lo que obligaría a la asignación de memoria para la cadena, también se puede utilizar esto:

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

Esto le debe permitir liberar explícitamente la memoria asignada cuando ya no se necesita.

Cuestiones relacionadas