fopen怎么比fopen更安全?

我正在处理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指针会发生什么(大多数实现可能会因空指针解引用而崩溃)。