-4

当我错误地遗漏了 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:代码::块

4

1 回答 1

1

“为什么编译器不会编译代码失败?它甚至没有警告我!”

这是因为 scanf() 的签名是int scanf ( const char * format, ... );表示...可变参数,而零参数也是有效的可变参数。似乎 gcc 不够聪明,无法在编译时解析格式字符串并生成警告。

“scanf() 现在是否正在尝试写入内存地址 NULL?例如:scanf("%c", NULL)"

这很可能是依赖于实现的,但很可能它只会尝试从带有格式字符串的第一个参数所在的堆栈中读取一些数据。

“为什么/如何在失败的 scanf() 语句下执行任何操作??”

scanf()解析第一个参数并检测到它需要一个指针时,它会在其中获得一些未初始化的内存返回随机垃圾,如果你“幸运”,你会在程序内存的某处获得一个“有效”地址,它不会出现段错误马上。这真的很不幸,因为(如您所见)有时会失败,有时却不会。这种内存损坏很难追踪,因为错误出现的点可能与它发生的点没有任何联系。

于 2013-03-30T19:46:16.297 回答