Getting access violation error while using %s in scanf_s

1

I am a beginner and I am learning C and using Visual Studio Code 2019 and I get an error like this:

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

Here is my code:

#include <stdio.h> 

int main() {
    char str[50];

    scanf_s("%s", &str);

    printf("%s", str);

    return 0;
}

I know it is a very noob type question but when I compile the same code with Code::Blocks, it runs fine but ultimately I have to use VScode to build projects so I am stuck here. How can I fix this problem?

c
windows
scanf
asked on Stack Overflow May 3, 2020 by Vishal Singh • edited May 3, 2020 by chqrlie

1 Answer

4

Your code has undefined behavior because you do not pass the size argument scanf_s expects after the destination pointer for the %s conversion. Furthermore, you should pass str, not &str although that should not cause a problem. You should also test if scanf_s succeeds to avoid calling printf with an uninitialized array if it fails, for example if the input stream is an empty file.

Finally, there is a problem with scanf_s that is well beyond your current skill level: this function is defined with different semantics on Windows and in the C Standard, so the way you can pass the size argument depends on the compiler.

For standard complying compilers, such as gcc and clang in linux and Mac/OS, you would use sizeof str which has type size_t, but on Windows you must cast this as (unsigned) because Microsoft's version of scanf_s expects this type, which has a different size on 64-bit systems. For this and other reasons, scanf_s should not be used in a portable program.

Here is a modified version for linux and Mac/OS:

#include <stdio.h> 

int main() {
    char str[50];

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

Here is a modified version for Windows, where the compiler insists on the use of scanf_s with non-standard semantics:

#include <stdio.h> 

int main() {
    char str[50];

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

The 49 in %49s prevents scanf_s from triggering an implementation defined exception.

answered on Stack Overflow May 3, 2020 by chqrlie • edited May 3, 2020 by chqrlie

User contributions licensed under CC BY-SA 3.0