2011-01-10 7 views
5

Ho un piccolo problema con il codice qui sotto. È un programma semplice che legge in 2 matrici di caratteri e un int. Quindi memorizza tutto il contenuto in un'altra stringa e lo stampa.Errore: lo stack attorno alla variabile "stringa" era danneggiato

#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; 
} 

Ora il programma sta funzionando benissimo, ma quando chiudo, ottengo il seguente errore: Run-Time Check Failure # 2 - Stack intorno al 'stringa' variabile è stato danneggiato. Questo è un po 'confuso e non riesco a capire dove sia il problema. Sarei grato per qualsiasi consiglio.

+1

Non correlato, ma se si ha C99 (o una garanzia di alcune parti di esso) si dovrebbe usare 'snprintf' invece di evitare che questo tipo di problema accada. –

risposta

13

Si sta scrivendo più caratteri in 'stringa' di quello che ha stanziato spazio per (vale a dire più di 50)

Ci sono 37 personaggi in "Your name is %s %s and you are %d years old." prima di aggiungere i valori per primo, ultimo e l'età. Ciò lascia solo 13 caratteri per tutte e tre le variabili. Quindi si riversa negli altri oggetti dichiarati dopo la 'stringa' variabile nello stack.

Come ha detto Jon, è consigliabile utilizzare le funzioni che limitano la quantità di scrittura (le varianti "n"), altrimenti queste possono essere fonti di exploit bufferoverrun.

BTW "string" è un nome molto scarso per una variabile.

1

direi che è qualcosa a che fare con il fatto che la lunghezza dell'array string è di 50 caratteri, si ha nel sprintf 37 (se ho contato a destra) più poi fino a 11 per first e un altro 16 per last , più forse 2 o 3 per l'età. Questo ammonta a più di 50. Tutto funziona bene, ma è molto probabile che si sovrascriva oltre la fine dei 50 caratteri allocati. Ciò funzionerà, ma corromperà lo stack, come hai osservato.

4

Oltre a qualsiasi altra cosa, è possibile avere un nome di massimo 10 caratteri e un cognome di massimo 15 caratteri. Se tali limiti vengono raggiunti (ma non superati) e l'età è un numero a due cifre, saranno necessari 66 caratteri, quindi sarà necessario dichiarare string come un array di 67 caratteri da gestire (per includere il terminatore null).

Oltre a questo, dovresti utilizzare le funzioni o le stringhe di formato che ti consentono di limitare la dimensione dell'input - attualmente se qualcuno immette un nome di lunghezza superiore a 10 caratteri (ecc.) Calpesti altri bit di memoria . È passato un po 'di tempo da quando ho scritto qualsiasi C, ma usare le stringhe di formato "% 10s" e "% 15s" può essere d'aiuto in questo senso - o usare fgets.

Allo stesso modo, suggerirei di utilizzare snprintf (o snprintf_s se disponibile) anziché sprintf per evitare il problema di sovravelocità. Utilizzare i valori di ritorno di tutti questi metodi per rilevare gli errori, troppo :)

+0

È possibile limitare la dimensione con 'scanf', ma il recupero aggraziato quando viene raggiunto il limite è inutilmente difficile, quindi +1 per raccomandare altre funzioni. –

2

È possibile limitare la quantità di caratteri scanf legge con

scanf("%9s", foo) 

che leggerà al massimo 9 caratteri, quindi aggiungere un NUL, che è adatto per un buffer di dimensioni 10.

Problemi correlati