有没有办法将 fopen_s() 与 GCC 一起使用,或者至少创建一个关于它的 #define ?

发布于 2024-08-06 18:32:46 字数 163 浏览 3 评论 0原文

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

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

对于 #define 有什么想法吗?

MSVC compiler says that fopen() is deprecated, and recommends the use of fopen_s().

Is there any way to use fopen_s() and still be portable?

Any ideas for a #define?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

凡间太子 2024-08-13 18:32:46

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

如果您坚持,您可以使用适配器函数(不一定是宏!)在没有 fopen_s() 的平台上委托 fopen(),但您必须请小心从 errno 映射 errno_t 返回代码的值。

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() 更安全,所以我通常会考虑可移植性。

Microsoft's *_s functions are unportable, I usually use equivalent C89/C99 functions and disable deprecation warnings (#define _CRT_SECURE_NO_DEPRECATE).

If you insist, you can use an adaptor function (not necessarily a macro!) that delegates fopen() on platforms that don't have fopen_s(), but you must be careful to map values of errno_t return code from 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;
}

However, I fail to see how fopen_s() is any more secure than fopen(), so I usually go for portability.

深空失忆 2024-08-13 18:32:46

在 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");

In C/C++ code,

#ifdef __unix
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL
#endif

In Makefile

CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL'

Attention that on success fopen_s return 0 while fopen return a nonzero file pointer. Therefore it is necessary to add "==NULL" to the end of macro, e.g.:

if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
与他有关 2024-08-13 18:32:46

如果您使用 C11,fopen_s 是一个标准库。

gcc中,您需要使用--std=c11参数。

if you are using C11, fopen_s is a standard library.

In gcc you need to use --std=c11 parameter.

彩虹直至黑白 2024-08-13 18:32:46

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

我过去是这样做的:

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

这个宏简单直接,对于快速而肮脏的事情来说足够好了,但是它不提供 fopen_s 的异常行为,并且它不会提供真正的 fopen_s 的安全性功能。

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

Many of Microsoft's secure functions are included in Annex K of the C11 standard, but it is not widely supported, so portability is still an issue. There is a need for the improved security in some applications; maybe the support will improve in the future.

I the past, I did it like this:

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

The macro is simple and straight forward, good enough for something quick and dirty, but it doesn't provide the exception behavior of fopen_s, and it won't provide the security of the real fopen_s function.

@Alex B's function approach above partially reproduces the proper behavior on failure; he returns errno (= EINVAL). His approach could be extended further by generating an invalid parameter exception to more fully reproduce the behavior of fopen_s.

孤寂小茶 2024-08-13 18:32:46
#define fopen_s(fp, fmt, mode)  ({\
    *(fp)=fopen( (fmt), (mode));\
    (*(fp) ) ? 0:errno;\
})
#define fopen_s(fp, fmt, mode)  ({\
    *(fp)=fopen( (fmt), (mode));\
    (*(fp) ) ? 0:errno;\
})
岁吢 2024-08-13 18:32:46

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

与所有边界检查函数一样,仅当实现定义了 __STDC_LIB_EXT1__ 并且用户定义了 __STDC_WANT_LIB_EXT1__ 时,才保证 fopen_s 可用。在包含 之前将 code> 转换为整数常量 1

Accroding to https://en.cppreference.com/w/c/io/fopen
it's possible to enable *_s functions on the standard library:

As with all bounds-checked functions, fopen_s is only guaranteed to be available if __STDC_LIB_EXT1__ is defined by the implementation and if the user defines __STDC_WANT_LIB_EXT1__ to the integer constant 1 before including <stdio.h>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文