2011-01-10 11 views
5

Tengo un pequeño problema con el código siguiente. Es un programa simple que lee en 2 matrices de char y un int. Luego almacena todo el contenido en otra cadena y la imprime.Error: la pila alrededor de la variable 'cadena' estaba dañada

#include <stdio.h> 
#include <string.h> 

int main() 

{ 
    char string [50]; 
    char first [11]; 
    char last [16]; 
    int age = 0; 


    printf("Please type in your first name: "); 
     scanf("%s", first); 

    printf("Please type in your last name: "); 
     scanf("%s", last); 

    printf("Please type in your age: "); 
     scanf("%d", &age); 

    sprintf(string, "Your name is %s %s and you are %d years old.", first, last, age); 
     puts(string); 

    getchar(); 
    getchar(); 

    return 0; 
} 

Ahora el programa está funcionando muy bien, pero cuando lo cierro, me sale el siguiente error: Run-Time Check Fracaso # 2 - Stack alrededor de la 'cadena' variable está dañado. Eso es un poco confuso y no puedo entender dónde está el problema. Estaría agradecido por algún consejo.

+1

No relacionado, pero si tiene C99 (o una garantía de algunas partes) debe utilizar 'snprintf' para evitar que ocurra este tipo de problema. –

Respuesta

13

Estás escribiendo más caracteres en 'cadena' de lo que se ha asignado espacio para (es decir, más de 50)

Hay 37 personajes de "Your name is %s %s and you are %d years old." antes de agregar los valores para la primera, la última y la edad. Eso deja solo 13 caracteres para las tres variables. Por lo tanto, se extiende a los otros valores declarados después de su variable 'cadena' en la pila.

Como mencionó Jon, es una buena práctica usar las funciones que limitan cuánto escriben (las variantes 'n'), de lo contrario, estas pueden ser fuentes de exploits de bufferoverrun.

BTW 'cadena' es un nombre muy pobre para una variable.

1

supongo que es algo que ver con el hecho de que la longitud de la matriz string es de 50 caracteres, que tiene en el sprintf 37 (si Conté derecha), además de a continuación, hasta un 11 por first y otro 16 para last , más tal vez 2 o 3 por edad. Eso suma más de 50. Todo funciona bien, pero es muy probable que sobrescriba más allá del final de los 50 caracteres asignados. Eso 'funcionará', pero corromperá la pila, como habrás observado.

4

Aparte de cualquier otra cosa, ha permitido el nombre de hasta 10 caracteres y un apellido de hasta 15 caracteres. Si se alcanzan esos límites (pero no se excede) y la edad es un número de dos dígitos, tomará 66 caracteres, por lo que tendría que declarar string como una matriz de 67 caracteres para hacer frente (para incluir el terminador nulo).

Más allá de eso, debe usar funciones o cadenas de formato que le permiten limitar el tamaño de la entrada - actualmente, si alguien ingresa un nombre de más de 10 caracteres (etc.) pisoteará otros bits de memoria . Ha pasado un tiempo desde que escribí C, pero usar cadenas de formato de "% 10s" y "% 15s" puede ser útil en este sentido, o use fgets.

Del mismo modo, le sugiero que use snprintf (o snprintf_s si está disponible) en lugar de sprintf para evitar el problema de la salida de exceso. Utilice los valores de retorno de todos estos métodos para detectar errores, también :)

+0

Puede limitar el tamaño con 'scanf', pero la recuperación elegante cuando se alcanza dicho límite es innecesariamente difícil, por lo tanto, +1 para recomendar otras funciones. –

2

Puede limitar la cantidad de caracteres scanf lee con

scanf("%9s", foo) 

que leerá como máximo 9 caracteres, tiene que poner un NUL, que es adecuado para un búfer de tamaño 10.

Cuestiones relacionadas