使用scanf_s报错:0xC0000005: Access violation writing location 0x00000000

在vs2010中写了一行scanf(“%s",name); 调式时 提示warning , 提示修改为scanf()使用可能会存在不安全,建议使用scanf_s() 但是我修改成scanf_s("%s",name)之后,正常运行没有问题,也没有了warning ,但是遇到scanf_s("%s",name)这句话时,我输入了一个name, Enter 一下就报如下错误:

0xC0000005: Access violation writing location 0x00000000

在MS系统中错误代号:0xC0000005 表示访问不存在的内存

原来,ANSI C中没有scanf_s() , 只有scanf(), scanf()在读取数据时不检查边界,所以可能会造成内在泄露。所以MS在vs2005及更高级版本中提供了scanf_s(),但是在调用它时,必须提供一个数字表明最多读取多少位字符。

[官方文档:http://msdn.microsoft.com/zh-cn/library/w40768et%28VS.80%29.aspx  ]

之所以出现:0xC0000005这样的错,是因为在调用的时候没有为它申请到内存,所以报访问内存不存在,因为我输入了字符串,这些字符串在buffer是有一个地址代表它们存在的位置的,但是调用scanf_s()时因为没有指定读取多少位字符, 所以它无法去读取内存buffer中的字符串,所以报内存不可读取的错误。 如果我们改成如下形式,给scanf_s()指定读取例如10个字符,即可顺利完成读取任务:

scanf_s("%s",name,10);

因为scanf() 在读取数据时不检查边界,由此可能造成安全隐患, 所以MS在vs2005版本及更高级版本中就建议使用scanf_s()来代替scanf()函数, 但是如果你坚持要使用scanf()函数的话,一般也不会出现什么问题, 不过vs在编译时会给出warning提示, 如果要消除这个提示, 只要在使用了scanf()的文件最开始的地方加入如下语句即可:

#pragma warning(disable:4996)

scanf_s函数也是从标准输入流中读取数据并把它们格式化写入到指定的变量中, 不像scanf()函数, scanf_s()函数在读取输入的字符时必须要为其指定一个缓冲区大小,这个缓冲区大小将作为一个附加参数在读取字符时 立即传入到scanf_s()函数。例如读取一个字符串,容纳这个字符串的缓冲区大小就被作为附加参数传入到scanf_s()中。

char s[10];

scanf_s("%9s",s,10);

注:这个缓冲区大小包括了结束符NULL,读取指令将使用这个缓冲区大小去读取相应长度的字符到缓冲区中,如果没有指定缓冲区大小,或者要读取的字符(即从键盘输入的字符)大于指定的缓冲区大小,那么什么也不会写入到缓冲区中。 注意上面说的缓冲区包括了后面的结束符NULL ,是在字符串中而言。

读取一个字符

char c;

scanf_s("%c",&c,1);

读取多字节不带null结束的字符串时,整型可以用如下方式读取:

char c[4];

scanf_s("%4c",&c,4);

如果你需要在不同的编译器中去编译的话, 那么采用条件编译是最好的选择:

 
#define MS2010
double getNumber(const char* prompt)
{
    double inputNumber = 0.0;
    puts(prompt);
#ifdef MS2010
    while((scanf_s("%lf",&inputNumber)) != 1)
#else
    while((scanf("%lf",&inputNumber)) != 1)
#endif
    {
        while(getchar() != '
');
        printf("You must enter a NUMBER --%s",prompt);
    }
    while(getchar() != '
');
    return (inputNumber);
}
 
 

[参考链接:http://faculty.edcc.edu/paul.bladek/CS131/scanf_s.htm]

原文地址:https://www.cnblogs.com/AI-Algorithms/p/3388017.html