Ошибка: стек вокруг переменной 'string' поврежден - PullRequest
6 голосов
/ 10 января 2011

У меня небольшая проблема с кодом ниже. Это простая программа, которая читает 2 массива char и int. Затем он сохраняет весь контент в другую строку и печатает его.

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

Теперь программа работает нормально, но когда я закрываю ее, я получаю следующую ошибку: Ошибка проверки во время выполнения # 2 - стек вокруг переменной 'string' поврежден. Это немного сбивает с толку, и я не могу понять, где проблема. Я был бы благодарен за любой совет.

Ответы [ 4 ]

14 голосов
/ 10 января 2011

Вы пишете больше символов в 'строку', чем выделено место (т. Е. Более 50)

В "Your name is %s %s and you are %d years old." содержится 37 символов * ДО того, как вы добавите значения для первого, последнего и возраста. Это оставляет только 13 символов для всех трех переменных. Таким образом, он перетекает в другие переменные, объявленные после вашей переменной 'string' в стеке.

Как упоминал Джон, рекомендуется использовать функции, ограничивающие объем написанного (варианты 'n'), в противном случае они могут быть источниками эксплойтов bufferoverrun.

Кстати, 'string' - очень плохое имя для переменной.

4 голосов
/ 10 января 2011

Помимо всего прочего, вы можете указать имя до 10 символов и фамилию до 15 символов.Если эти пределы достигнуты (но не превышены), а возраст представляет собой двузначное число, которое займет 66 символов - поэтому вам придется объявить string массивом из 67 символов, чтобы справиться (включая нулевой терминатор).

Помимо этого, вы должны использовать функции или строки форматирования, которые позволяют ограничивать размер ввода - в настоящее время, если кто-то вводит имя длиной более 10 символов (и т. Д.), Вы будете растоптывать другиебиты памяти.Прошло много времени с тех пор, как я написал любой C, но использование форматных строк "% 10s" и "% 15s" может помочь в этом отношении - или использовать fgets.

Аналогично, я бы предложил использоватьsnprintf (или snprintf_s, если он доступен вам) вместо sprintf, чтобы избежать проблемы превышения выходного сигнала.Используйте возвращаемые значения всех этих методов также для обнаружения ошибок:)

2 голосов
/ 10 января 2011

Вы можете ограничить количество символов, которые scanf читает с помощью

scanf("%9s", foo)

, который будет читать не более 9 символов, а затем добавить NUL, который подходит для буфера размером 10.

1 голос
/ 10 января 2011

Я думаю, это как-то связано с тем, что длина массива string составляет 50 символов, у вас в sprintf 37 (если я считал правильно) плюс затем до 11 для first и другое16 для last, плюс 2 или 3 для возраста.Это в сумме превышает 50. Все работает нормально, но вы, скорее всего, перезаписываете после окончания выделенных 50 символов.Это будет «работать», но, как вы заметили, испортит стек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...