MSVC 编译器表示fopen()
已弃用,并建议使用fopen_s()
.
有什么方法可以使用fopen_s()
并且仍然可以携带吗?
有什么想法#define
吗?
MSVC 编译器表示fopen()
已弃用,并建议使用fopen_s()
.
有什么方法可以使用fopen_s()
并且仍然可以携带吗?
有什么想法#define
吗?
Microsoft 的*_s
功能不可移植,我通常使用等效的 C89/C99 功能并禁用弃用警告 ( #define _CRT_SECURE_NO_DEPRECATE
)。
如果你坚持,你可以使用一个适配器函数(不一定是宏!)在fopen()
没有.fopen_s()
errno_t
errno
errno_t fopen_s(FILE **f, const char *name, const char *mode) {
errno_t ret = 0;
assert(f);
*f = fopen(name, mode);
/* Can't be sure about 1-to-1 mapping of errno and MS' errno_t */
if (!*f)
ret = errno;
return ret;
}
但是,我看不出fopen_s()
有什么比 更安全fopen()
,所以我通常会选择便携性。
在 C/C++ 代码中,
#ifdef __unix
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL
#endif
在 Makefile
CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL'
请注意,成功时 fopen_s 返回 0 而 fopen 返回非零文件指针。因此需要在宏的末尾添加“==NULL”,例如:
if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
Microsoft 的许多安全功能都包含在 C11 标准的 Annex K 中,但并未得到广泛支持,因此可移植性仍然是一个问题。在某些应用程序中需要提高安全性;也许将来支持会有所改善。
我过去,我是这样做的:
#define fopen_s(fp, fmt, mode) *(fp)=fopen( (fmt), (mode))
该宏简单直接,足以应付快速而肮脏的事情,但它不提供 fopen_s 的异常行为,也不会提供真正的 fopen_s 函数的安全性。
@Alex B 上面的函数方法部分地再现了失败时的正确行为;他返回 errno (= EINVAL)。他的方法可以通过生成无效参数异常来进一步扩展,以更全面地再现 fopen_s 的行为。
#define fopen_s(fp, fmt, mode) ({\
*(fp)=fopen( (fmt), (mode));\
(*(fp) ) ? 0:errno;\
})
根据https://en.cppreference.com/w/c/io/fopen 可以在标准库上启用 *_s 函数:
与所有边界检查函数一样,只有在由实现定义并且用户在 include之前定义为整数常量
fopen_s
时才保证可用。__STDC_LIB_EXT1__
__STDC_WANT_LIB_EXT1__
1
<stdio.h>