scanf_s中的访问冲突

时间:2018-10-28 22:42:15

标签: c visual-studio runtime-error

我正在尝试制作一个程序,以查看我可以使用C语言中的结构做什么。但是在2的主函数中出现错误:

  

在StructureTest.exe中的0x5C26D3EC(ucrtbased.dll)处引发了异常:

     

0xC0000005:访问冲突写入位置0x01341000。发生

我也得到了一些compiler warnings。这是我的代码:

scanf_s("%s", &user.name)

我对结构还没有真正的经验,但是我怀疑它可能与数组和指针以及我写的名字无关。

2 个答案:

答案 0 :(得分:3)

您没有显示输入给程序的输入。

程序中有一些小错误,有一些大错误:

  • 首先,您在分配char数组方面太过落后了。例如,month结构中的birthdate字段只有9个空格来存储月份,这意味着您不能像september那样存储9个字符加一个的月份。字符串末尾的\0 nul字符。如果您不小心,这可能是执行过程中的问题。
  • struct直接按值传递 到函数是不常见的做法,因为这使编译器将完整的结构内容复制到参数堆栈中。通过引用传递结构更为常见,如

    void printinfo(struct info *user);
    

    然后将其称为

    printinfo(&user);
    

    这使编译器仅传递指向该结构的指针,从而节省了时间和内存。

我在在线手册中找不到scanf_s函数,您从哪里得到的?好吧,经过一番挖掘,我从VC手册中找到了这些功能(不是标准的,只是Microsoft扩展):

  

与scanf和wscanf不同,scanf_s和wscanf_s 要求为所有类型为c,C,s,S或包含在[]中的字符串控制集的输入参数指定缓冲区大小。以字符为单位的缓冲区大小在指向缓冲区或变量的指针之后紧随作为附加参数传递 ...

因此您必须使用

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

与您正在阅读的其他字符串相同。

注意

这些带有后缀_s的函数只是编译器的Microsoft扩展。它们不是可移植的(无论如何也不是标准的),并且不会出现在大多数C实现中。最好不要使用它们,除非您将仅使用Microsoft C编译器(并且不保证它们将来会消失)。除了使用非标准函数外,还有其他检查缓冲区大小的方法,例如

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

(如果需要将大小作为参数传递,则可以执行以下操作):

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

将完成工作,或者

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

(此调用要求您从字符串中删除最后一个\n),这两个调用都是标准的,包含在<stdio.h>中。

答案 1 :(得分:0)

除了other answer中提到的使用 [215, 142, 235, 143, 249, 164] 的问题之外,您还提供了错误的参数:

scanf_s

由于scanf_s("%s", &user.origin); 是指向origin的指针,所以这不是正确的类型。您需要提供一个char,但您需要提供一个char *