2009-10-03 1 views
12

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

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

Любые идеи для #define?

+0

Аналогичная проблема [здесь] (http://stackoverflow.com/questions/14386/fopen-deprecated-warning). – luvieere

ответ

23

Функции 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(), поэтому я обычно хожу на портативности.

+5

Microsoft LOVES делает свою собственную версию вещей. Интересно, почему ... – LiraNuna

+9

Забавно, что теперь они являются частью C11 (хотя и в дополнительном приложении K). – rubenvb

+0

Намного лучше, чем мой (теперь бывший, а не тот, который мне больше нужен).Ваш функциональный подход частично воспроизводит поведение fopen_s при ошибке, возвращая errno (= EINVAL, т. Е. 22, fwiw). Вы могли бы также генерировать * недопустимое исключение параметра *, чтобы более точно соответствовать поведению fopen_s. – riderBill

4

В 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, а Еореп возвращает ненулевой указатель на файл. Поэтому необходимо, чтобы добавить "== NULL" в конце макроса, например:

if (fopen_s(&pFile,filename,"r")) perror("cannot open file"); 
1

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

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

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

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

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

Смежные вопросы