fopen_s怎么能比开口更安全
How can fopen_s be more safe than fopen?
我正在为Windows
平台编写遗留代码。当我在 VS2013
中编译代码时,它会给出以下警告:
错误 C4996:"
fopen
":此函数或变量可能不安全。请考虑改用fopen_s
。要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS。有关详细信息,请参阅联机帮助。
它还会对sprintf
发出环境警告.我知道sprintf_s
比 sprintf 更安全,因为缓冲区溢出。
但是怎么能fopen_s比fopen
更安全,没有缓冲区溢出的机会,因为fopen
不接受缓冲区。任何人都可以提供fopen
不安全的案例,而fopen_s
是安全的吗?
,s
并不代表"安全",它代表"增强的安全性"。对于fopen_s
,在尝试打开文件之前会检查参数的有效性。
使用 fopen
,您可以为文件名传递 NULL 指针,所有内容很可能会崩溃。 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
形成对比, 声明文件名和模式必须都指向字符串,但不指定如果提供 NULL 指针会发生什么(大多数实现可能会因空指针取消引用而崩溃)。
> 当 VS2005 问世时,我认为他们的"让我们制作专有函数而不是给人们snprintf()
"只是Microsoft走得太远,因为如果传递 NULL 指针,两者都会(默认情况下)引发 win32 异常(尽管fopen
会引发STATUS_ACCESS_VIOLATION
而fopen_s
会引发STATUS_INVALID_PARAMETER
)。这意味着两者都会导致程序立即崩溃,除非添加特定于 Win32 的代码来处理异常。
但是,在CRT源代码中窥视确实揭示了一个小差异:fopen
使用的共享标志是完全允许的,而fopen_s
使用的共享标志禁止其他进程打开文件进行写入。这样,fopen_s
更安全,因为这意味着文件不会在您的进程脚下更改。
- Arduino millis() - millis() 怎么能等于 0 以外的任何东西?
- 我已经建立了递归关系,它找到了两个字符串之间最长的连续公共字符串,我怎么能跳过其中一个字符串中的一个字符
- 我们怎么能 me 字符数组只接受 C++ 中的字母
- 你怎么能emplace_back错误的类型?
- 我怎么能有一个以2D数组为参数的函数,而数组有一个我想更改的参数/维度
- 我怎么能把它转换成c++呢
- 我有一个调用ID3D11DeviceContext::CopySubresourceRegion的循环.我怎么能强制等待
- 类定义怎么能不占用内存?
- 怎么能用memcpy复制工会简单的成员?
- 当 do-while 再次启动时,对象将被删除.我怎么能阻止它
- 指针怎么能有一个字符串作为它的值
- 一个函数怎么能完成它的目标,只是在返回主函数后崩溃?
- 这两个指针怎么能有相同的值
- glTranslatef拉伸我的球体,我怎么能不拉伸它就平移球体
- 我怎么能像 numpy 那样从 MxN 矩阵中减去 1xN 特征矩阵
- 我怎么能写一个长度函数来返回间隔的长度
- 我怎么能设法从我的代码中获得复数的答案
- 我怎么能在不使用BITSet的情况下知道C 中的位状态
- 如果指针已经被删除,指针容器怎么能拥有指针的所有权
- fopen_s怎么能比开口更安全