我正在处理Windows
平台的遗留代码。 当我在VS2013
编译代码时,会发出以下警告:
“错误C4996:' fopen
':这个函数或variables可能是不安全的,请考虑使用fopen_s
来取消弃用,请使用_CRT_SECURE_NO_WARNINGS。有关详细信息,请参阅联机帮助。
而且它也会给sprintf
惊人的警告。 我明白,由于缓冲区溢出, sprintf_s
比sprintf更安全。
但是怎样才能比fopen
更安全,因为fopen
不接受缓冲区,没有缓冲区溢出的机会。 任何人都可以提供一个案件fopen
是不安全的, fopen_s
是安全的?
在这种情况下, s
不代表“安全”,代表“安全性增强”。 对于fopen_s
,在尝试打开文件之前检查参数的有效性。
使用fopen
,你可以传递一个空指针作为文件名,一切都很可能会崩溃。 fopen_s
没有这个问题(a) 。
请记住,像fopen_s
这样的边界检查接口是ISO标准的一个可选部分,详见附录K(无论如何,C11)。 如果你知道你作为一个编码器正在做什么,实现并不需要提供它们,老实说, fopen
和许多其他所谓的不安全函数是完全安全的。
有趣的是, fopen_s
会捕获NULL指针,但不会导致无效指针,因此为什么它的安全性得到了提升而不是安全 – 如果您传递了一个无效的非NULL指针,仍然会造成一些损害。
其他“安全”功能强制您提供目标缓冲区大小也是安全的,只要您通过正确的大小。 传递太大的东西,所有的投注都关闭。
(a)从C11 K.3.5.2.1 The fopen_s function
:
errno_t fopen_s ( FILE * restrict * restrict streamptr, const char * restrict filename, const char * restrict mode);
运行约束
streamptr,文件名或模式都不能是空指针。
如果存在运行时约束冲突,fopen_s不会尝试打开文件。 此外,如果streamptr不是空指针,fopen_s将* streamptr设置为空指针。
与C11 7.20.5.3 The fopen function
对比C11 7.20.5.3 The fopen function
声明文件名和模式必须都指向一个字符串,但不指定如果提供一个NULL指针会发生什么(大多数实现可能会因空指针解引用而崩溃)。