fopen_s如何比fopen更安全?

Zij*_*gWu 22 c++ windows crt msvcrt tr24731

我正在研究用于Windows平台的遗留代码.当我编译代码时VS2013,它会发出以下警告:

错误C4996:' fopen':此函数或变量可能不安全.考虑fopen_s改用.要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS.详情请参见在线帮助."

它也会给出一个熟悉的警告sprintf.sprintf_s由于缓冲区溢出,我理解比sprintf更安全.

但是如何使fopen_s更安全fopen,因为fopen不接受缓冲区就没有缓冲区溢出的可能性.任何人都可以提供一个fopen不安全的案件,fopen_s是否安全?

pax*_*blo 25

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

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

请记住,这些边界检查接口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);
Run Code Online (Sandbox Code Playgroud)

运行约束

streamptr,filename或mode都不是空指针.

如果存在运行时约束冲突,则fopen_s不会尝试打开文件.此外,如果streamptr不是空指针,则fopen_s将*streamptr设置为空指针.

相比之下,C11 7.20.5.3 The fopen function文件名和模式必须指向一个字符串,但没有指定如果你提供一个NULL指针会发生什么(大多数实现可能会崩溃与空指针解除引用).

  • 请注意,标准C库在[C11§7.1.4库函数的使用](https://port70.net/~nsz/c/c11/n1570.html#7.1.4)中指定:_以下每个语句均适用除非在以下详细说明中另有明确说明,否则:如果函数的参数具有无效值(例如…,或程序地址空间外的指针,或空指针或指向不可修改的存储的指针)当相应的参数不为const限定时)或...,则行为是不确定的。 (2认同)