20

MSVC 编译器表示fopen()已弃用,并建议使用fopen_s().

有什么方法可以使用fopen_s()并且仍然可以携带吗?

有什么想法#define吗?

4

6 回答 6

32

Microsoft 的*_s功能不可移植,我通常使用等效的 C89/C99 功能并禁用弃用警告 ( #define _CRT_SECURE_NO_DEPRECATE)。

如果你坚持,你可以使用一个适配器函数(不一定是宏!)在fopen()没有.fopen_s()errno_terrno

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(),所以我通常会选择便携性。

于 2009-10-03T08:44:32.840 回答
8

在 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");
于 2013-03-06T23:10:26.307 回答
8

如果您使用的是 C11,fopen_s则为标准库:

http://en.cppreference.com/w/c/io/fopen

gcc你需要使用--std=C11参数。

于 2015-03-08T18:10:05.770 回答
3

Microsoft 的许多安全功能都包含在 C11 标准的 Annex K 中,但并未得到广泛支持,因此可移植性仍然是一个问题。在某些应用程序中需要提高安全性;也许将来支持会有所改善。

我过去,我是这样做的:

  #define fopen_s(fp, fmt, mode)          *(fp)=fopen( (fmt), (mode))

该宏简单直接,足以应付快速而肮脏的事情,但它不提供 fopen_s 的异常行为,也不会提供真正的 fopen_s 函数的安全性。

@Alex B 上面的函数方法部分地再现了失败时的正确行为;他返回 errno (= EINVAL)。他的方法可以通过生成无效参数异常来进一步扩展,以更全面地再现 fopen_s 的行为。

于 2016-02-04T06:24:24.510 回答
-1
#define fopen_s(fp, fmt, mode)  ({\
    *(fp)=fopen( (fmt), (mode));\
    (*(fp) ) ? 0:errno;\
})
于 2019-07-23T14:36:21.850 回答
-2

根据https://en.cppreference.com/w/c/io/fopen 可以在标准库上启用 *_s 函数:

与所有边界检查函数一样,只有在由实现定义并且用户在 include之前定义为整数常量fopen_s时才保证可用。__STDC_LIB_EXT1____STDC_WANT_LIB_EXT1__1<stdio.h>

于 2018-11-20T18:54:55.790 回答