[英]Is there a way to use fopen_s() with GCC or at least create a #define about it?
MSVC 編譯器說fopen()
已棄用,並建議使用fopen_s()
。
有什么方法可以使用fopen_s()
並且仍然可以移植嗎?
#define
有什么想法嗎?
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()
更安全,所以我通常會選擇可移植性。
在 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");
如果您使用的是 C11, fopen_s
是一個標准庫。
在gcc
中,您需要使用--std=c11
參數。
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 函數:
與所有邊界檢查函數一樣,只有在實現定義了
__STDC_WANT_LIB_EXT1__
並且用戶在包含<stdio.h>
之前將__STDC_LIB_EXT1__
定義為整數常量1
時,才保證fopen_s
可用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.