Ошибка получения доступа при использовании% s в scanf_s - PullRequest
1 голос
/ 03 мая 2020

Я новичок, изучаю C и использую код Visual Studio 2019, и я получаю сообщение об ошибке, подобное этому:

Exception thrown at 0x7C97E63C (ucrtbased.dll) in string.exe: 0xC0000005: Access violation writing location 0x00900000".

Вот мой код:

#include <stdio.h> 

int main() {
    char str[50];

    scanf_s("%s", &str);

    printf("%s", str);

    return 0;
}

Я знаю, что это очень типичный вопрос, но когда я компилирую тот же код с Code :: Blocks, он работает нормально, но в конечном итоге мне приходится использовать VScode для создания проектов, поэтому я застрял здесь. Как я могу решить эту проблему?

1 Ответ

4 голосов
/ 03 мая 2020

Ваш код имеет неопределенное поведение, потому что вы не передаете аргумент размера, который scanf_s ожидает после целевого указателя для преобразования %s. Кроме того, вы должны передать str, а не &str, хотя это не должно вызывать проблем. Вы также должны проверить, если scanf_s удастся избежать вызова printf с неинициализированным массивом, если он потерпит неудачу, например, если входной поток является пустым файлом.

Наконец, существует проблема с scanf_s это намного выше вашего текущего уровня квалификации: эта функция определена с различной семантикой в ​​Windows и в C Standard, поэтому способ передачи аргумента размера зависит от компилятора.

Для стандарта компиляторы, такие как gcc и clang в linux и Mac / OS, вы должны использовать sizeof str с типом size_t, но в Windows вы должны привести его к (unsigned), потому что версия Microsoft scanf_s ожидает этот тип, который имеет другой размер в 64-битных системах. По этой и другим причинам scanf_s не следует использовать в переносимой программе.

Вот модифицированная версия для linux и Mac / OS:

#include <stdio.h> 

int main() {
    char str[50];

    if (scanf("%49s", str) == 1) {
        printf("%s\n", str);
    }
    return 0;
}

Вот модифицированная версия для Windows, где компилятор настаивает на использовании scanf_s с нестандартной семантикой:

#include <stdio.h> 

int main() {
    char str[50];

    if (scanf_s("%49s", str, (unsigned)sizeof(str)) == 1) {
        printf("%s\n", str);
    }
    return 0;
}

49 в %49s не позволяет scanf_s запускать реализацию, определенную исключение.

...