Is there a way to use fopen_s() with GCC or at least create a #define about it?

前端 未结 6 835
遇见更好的自我
遇见更好的自我 2020-12-05 10:54

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

Is there any way to use fopen_s() and stil

相关标签:
6条回答
  • 2020-12-05 11:18

    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.

    0 讨论(0)
  • 2020-12-05 11:25
    #define fopen_s(fp, fmt, mode)  ({\
        *(fp)=fopen( (fmt), (mode));\
        (*(fp) ) ? 0:errno;\
    })
    
    0 讨论(0)
  • 2020-12-05 11:26

    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.

    0 讨论(0)
  • 2020-12-05 11:31

    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>.

    0 讨论(0)
  • 2020-12-05 11:34

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

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

    in gcc you need to use --std=C11 parameter.

    0 讨论(0)
  • 2020-12-05 11:40

    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");
    
    0 讨论(0)
提交回复
热议问题