简体   繁体   English

scanf_s中的访问冲突

[英]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) : 我正在尝试创建一个程序,只是看看我可以用C语言中的结构做什么。但是在scanf_s("%s", &user.name)的主函数中scanf_s("%s", &user.name)

Exception thrown at 0x5C26D3EC (ucrtbased.dll) in StructureTest.exe: 在StructureTest.exe中的0x5C26D3EC(ucrtbased.dll)抛出异常:

0xC0000005: Access violation writing location 0x01341000. 0xC0000005:访问冲突写入位置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. 首先,你在char数组的分配上太过分了。 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 . 例如, birthdate结构中的month字段只有9个空格来存储月份,这意味着您不能存储像september那样需要9个字符的月份以及字符串末尾的\\0 nul字符的一个月份。 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. struct直接通过值传递给函数并不常见,因为这会使编译器将完整的struct内容复制到参数堆栈中。 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? 我在手册中没有找到scanf_s函数,你从哪里得到它? Well, after some digging, I found them... from the VC manual for those functions (not standard, just a Microsoft extension): 好吧,经过一番挖掘后,我发现它们......来自VC手册中的那些功能(不是标准的,只是微软的扩展):

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 []. 与scanf和wscanf不同,scanf_s和wscanf_s 要求为所有包含在[]中的c,C,s,S或字符串控件集的输入参数指定缓冲区大小。 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 . 那些_s后缀函数只是其编译器的Microsoft扩展 They are not portable (nor standard in anyway) and don't appear in the majority of C implementations. 它们不是可移植的(无论如何也不是标准的)并且不会出现在大多数C实现中。 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). 最好不要使用它们,除非你只使用Microsoft C编译器(并且你不保证它们将来会消失)。 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> . (此调用要求您消除字符串中的最后一个\\n )这两个调用都是标准的,包含在<stdio.h>

Besides the problems using scanf_s mentioned in the other answer you also provide a wrong parameter: 除了使用另一个答案中提到的scanf_s的问题,你还提供了一个错误的参数:

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

With origin being a pointer to char , that's not the correct type. 由于origin是指向char的指针,这不是正确的类型。 You need to provide a char * but you provide a char ** . 你需要提供一个char *但你提供了一个char **

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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