简体   繁体   中英

Access violation in scanf_s

I'm trying to make a program to just see what I can do with structures in C. But getting an error in the main function at scanf_s("%s", &user.name) :

Exception thrown at 0x5C26D3EC (ucrtbased.dll) in StructureTest.exe:

0xC0000005: Access violation writing location 0x01341000. occurred

I also get some compiler warnings . This is my code:

#include <stdio.h>

struct birthdate {
    int day;
    char month[9];
    int year;
};

typedef struct birthdate dob;
    struct info {
    char name[40];
    dob birthdate;
    int age;
    char sex[6];
    char *origin; 
};
void printinfo(struct info user) {
    printf("---- User Data ----\n");
    printf("Name: %s\n", user.name);
    printf("Date of birth: %d/%s/%d\n", user.birthdate.day, 
    user.birthdate.month, user.birthdate.year);
    printf("Age: %d\n", user.age);
    printf("Sex: %s\n", user.sex);
    printf("Country of origin: %s", user.origin);
}

int main() {
    printf("--Please enter your info--\n");
    struct info user;   
    printf("Please enter your name: ");
    scanf_s("%s", &user.name); // <-- exception thrown here
    printf("Please enter your date of birth in the format (dd/mm/yyyy): ");
    scanf_s("%d %s %d", &user.birthdate.day, &user.birthdate.month,
    &user.birthdate.year);
    printf("Please enter your age: ");
    scanf_s("%d", &user.age);
    printf("Please enter your gender ([M]ale/[F]emale): ");
    scanf_s("%s", &user.sex);
    printf("Please enter your country of origin: ");
    scanf_s("%s", &user.origin); // <- Another exception thrown here

    printf("\n\n");
    printinfo(user);

    printf("\nPress ENTER to continue..");
    getchar();
    return 0;
}

I'm not really experienced with structures yet, but I suspect it might have something to do with arrays and pointers, and the name I write in going into nowhere.

You didn't show the input you feed to the program.

There are some minor mistakes and some major in your program:

  • First, you have been too tigth in the allocation of char arrays. For example, month field in birthdate struct has only 9 spaces to store the month, and this means you cannot store a month like september that requires 9 characters plus one more for the \\0 nul character at the end of the string . This can be the problem with your execution if you aren't careful.
  • It's not common practice to pass struct s directly by value to a function, as this makes the compiler to copy the complete struct contents into the parameter stack. It's more common to pass the struct by reference, as in

     void printinfo(struct info *user); 

    and then calling it as

     printinfo(&user); 

    which makes the compiler to pass only a pointer to the structure, saving time and memory.

I have not found the scanf_s function in my manual online, where did you get it? Well, after some digging, I found them... from the VC manual for those functions (not standard, just a Microsoft extension):

Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or string control sets that are enclosed in []. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable ...

so you must use

scanf_s("%s", &user.name, sizeof user.name - 1);

and the same for the other strings you are reading.

NOTE

Those _s suffixed functions are only Microsoft extensions to their compiler . They are not portable (nor standard in anyway) and don't appear in the majority of C implementations. It's better not to use them, except if you are going to use only Microsoft C compilers (and you are not warranted for them to disappear in the future). There are other means to check for buffer size than to use nonstandard functions, eg

scanf("%.39s", user.name); /* there's no need to use the & operator here */

(in case you need to pass the size as a parameter, you can do the following):

SCANF("%.*s", sizeof user.name - 1, user.name);

will do the work, or

fgets(user.name, sizeof user.name, stdin);

(this call requires you to eliminate the last \\n from the string) both of these calls are standard, included in <stdio.h> .

Besides the problems using scanf_s mentioned in the other answer you also provide a wrong parameter:

scanf_s("%s", &user.origin);

With origin being a pointer to char , that's not the correct type. You need to provide a char * but you provide a char ** .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM