当我错误地遗漏了scanf()函数的第二个参数时,程序仍然编译并运行但可执行文件遇到以下错误:“APPCRASH”,异常代码为“c0000005”(这意味着有一个内存)访问违规AFAIK)。我做了一些实验,看起来崩溃总是发生在调用scanf()的函数超出范围但是我已经意识到它在实际调用中发生的事情比不是。例如:
void afunction (void) {
printf("This works fine!");
scanf("%c"); /* NOTE the second parameter omission */
printf("This showed up a few times, misleading me");
}
我现在有三个问题:
1)为什么编译器无法编译代码?它甚至没有警告我!
2)scanf()现在尝试写入内存地址NULL吗?例如:scanf(“%c”,NULL)
3)为什么/如何在失败的scanf()语句下面执行任何操作?
附加信息:
平台:Windows
编译器:GCC
IDE:代码::块
答案 0 :(得分:1)
这是因为scanf()的签名是int scanf ( const char * format, ... );
,...
代表varargs,零参数也是有效的varargs。似乎gcc不够智能,无法在编译时解析格式字符串并生成警告。
这很可能是依赖于实现的,但很可能只是尝试从堆栈中读取一些带有格式字符串的第一个参数的数据。
当scanf()
解析第一个参数并检测到它需要一个指针时,它会在其中获得一些未初始化的内存返回随机垃圾,如果你“幸运”,你会得到一个“有效”的地址。程序的内存,它不会立即进行分段。这真的很不幸,因为(正如你所看到的)有时会失败,有时它却没有。这些内存损坏很难追踪,因为错误表面可能与它发生的点没有任何关联。