Есть ли способ использовать fopen_s () с GCC или хотя бы создать #define? - PullRequest
14 голосов
/ 03 октября 2009

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

Есть ли способ использовать fopen_s() и при этом быть переносимым?

Есть идеи для #define?

Ответы [ 5 ]

26 голосов
/ 03 октября 2009

Microsoft *_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(), поэтому я обычно обращаюсь к переносимости.

10 голосов
/ 08 марта 2015

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

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

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

7 голосов
/ 07 марта 2013

В коде 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» в конец макроса, например ::100100

if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
2 голосов
/ 04 февраля 2016

Многие из безопасных функций Microsoft включены в Приложение K стандарта C11, но они широко не поддерживаются, поэтому переносимость все еще остается проблемой. Существует необходимость в улучшенной безопасности в некоторых приложениях; возможно, поддержка улучшится в будущем.

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

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

Макрос прост и понятен, достаточно хорош для чего-то быстрого и грязного, но он не обеспечивает исключительного поведения fopen_s и не обеспечивает безопасность реальной функции fopen_s.

@ Функциональный подход Алекса Б выше частично воспроизводит правильное поведение при сбое; он возвращает errno (= EINVAL). Его подход может быть расширен за счет генерации недопустимого исключения параметра для более полного воспроизведения поведения fopen_s.

0 голосов
/ 20 ноября 2018

По https://en.cppreference.com/w/c/io/fopen можно включить функции * _s в библиотеке stdc

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

...