Есть ли способ использовать fopen_s() с GCC или, по крайней мере, создать #define для этого?

StackOverflow https://stackoverflow.com/questions/1513209

  •  19-09-2019
  •  | 
  •  

Вопрос

Компилятор MSVC говорит , что fopen() является устаревшим и рекомендует использовать fopen_s().

Есть ли какой-нибудь способ использовать fopen_s() и при этом оставаться портативным?

Есть какие-нибудь идеи для #define?

Это было полезно?

Решение

Корпорация Майкрософт *_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(), поэтому я обычно предпочитаю мобильность.

Другие советы

если вы используете C11, fopen_s является стандартной библиотекой:

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

в gcc вам нужно использовать --std=C11 параметр.

В коде 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 включены в приложение K стандарта C11, но оно не пользуется широкой поддержкой, поэтому переносимость по-прежнему остается проблемой.Существует необходимость в повышении безопасности в некоторых приложениях;возможно, поддержка улучшится в будущем.

Я в прошлом, я сделал это вот так:

  #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 в стандартной библиотеке:

Как и во всех функциях с проверкой границ, fopen_s гарантированно будет доступен только в том случае, если __STDC_LIB_EXT1__ определяется реализацией, и если пользователь определяет __STDC_WANT_LIB_EXT1__ к целочисленной константе 1 перед включением <stdio.h>.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top