c++ - fopen_s 如何比 fopen 更安全?

标签 c++ windows msvcrt crt tr24731

我正在为 Windows 平台处理遗留代码。当我在 VS2013 中编译代码时,它会给出以下警告:

error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details."

它也会对 sprintf 给出类似的警告。我知道 sprintf_s 因为缓冲区溢出比 sprintf 更安全。

可是怎么可能fopen_sfopen 更安全,没有缓冲区溢出的机会,因为 fopen 不接受缓冲区。谁能提供一个案例 fopen 是不安全的,而 fopen_s 是安全的?

最佳答案

s 在这种情况下不代表“安全”,它代表“安全增强”。对于 fopen_s,在尝试打开文件之前检查参数的有效性。

使用 fopen,您可以为文件名传递一个 NULL 指针,然后一切都很可能会崩溃。 fopen_s 没有那个问题(a).

请记住,像 fopen_s 这样的边界检查接口(interface)是 ISO 标准的一个可选部分,详见附录 K(无论如何都在 C11 中)。实现并不是必需来提供它们,老实说,fopen 和许多其他所谓的不安全函数,如果你知道自己在做什么,那么它们是完全安全的编码员。

有趣的是,fopen_s 将为您捕获 NULL 指针,但不会捕获无效指针,因此它的安全性增强而不是安全 - 如果您传递一个无效但非空指针。

只要您传递正确的大小,其他强制您提供目标缓冲区大小的“安全”函数也是安全的。传递太大的东西,所有的赌注都被取消了。


(a)来自C11 K.3.5.2.1 fopen_s函数:

errno_t fopen_s (
    FILE * restrict * restrict streamptr,
    const char * restrict      filename,
    const char * restrict      mode);

Runtime-constraints

None of streamptr, filename, or mode shall be a null pointer.

If there is a runtime-constraint violation, fopen_s does not attempt to open a file. Furthermore, if streamptr is not a null pointer, fopen_s sets *streamptr to the null pointer.

对比 C11 7.20.5.3 The fopen function 声明文件名和模式必须都指向一个字符串,但没有指定如果你提供一个 NULL 指针会发生什么(大多数实现会可能会因空指针取消引用而崩溃)。

关于c++ - fopen_s 如何比 fopen 更安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19396116/

相关文章:

c++ - 尝试在 avl 树中实现查找

c++ - 如何将 SIGFPE 与信号一起使用?

java - 如何为任务计划程序执行控制台 Java 应用程序?

c++ - ClickOnce:在用户机器上获取 MSVCRT C++ DLL

c - MSVCRT:sin、cos等的实现(源码)在哪里?

C++ 用零填充二维数组

c++ - forked进程偶发的栈指针段错误

windows - 安装 JDK 后 Chrome 无法运行

windows - 如何在 Windows 中解析规范文件名?

python - 尝试在 Python 中创建打印计算器程序,程序无限输出 0