我正在为 Windows
平台处理遗留代码。当我在 VS2013
中编译代码时,它会给出以下警告:
error C4996: '
fopen
': This function or variable may be unsafe. Consider usingfopen_s
instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details."
它也会对 sprintf
给出类似的警告。我知道 sprintf_s
因为缓冲区溢出比 sprintf 更安全。
可是怎么可能fopen_s比 fopen
更安全,没有缓冲区溢出的机会,因为 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/