Existe uma maneira de usar fopen_s () com GCC ou pelo menos criar um #define sobre isso?
-
19-09-2019 - |
Pergunta
compilador MSVC diz que fopen()
está obsoleta, e recomenda o uso de fopen_s()
.
Existe alguma maneira de usar fopen_s()
e ainda ser portátil?
Todas as idéias para um #define
?
Solução
funções *_s
da Microsoft são portável, eu costumo usar equivalentes funções C89 / C99 e desativar os avisos de descontinuação (#define _CRT_SECURE_NO_DEPRECATE
).
Se você insistir, você pode usar uma função de adaptador (não necessariamente uma macro!) Que os delegados fopen()
em plataformas que não têm fopen_s()
, mas você deve ter cuidado para mapear valores de código errno_t
retorno de 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;
}
No entanto, eu não consigo ver como fopen_s()
é mais seguro do que fopen()
, então eu costumo ir para a portabilidade.
Outras dicas
Se você estiver usando C11, fopen_s
é uma biblioteca padrão:
http://en.cppreference.com/w/c/io/fopen
em gcc
você precisa usar o parâmetro --std=C11
.
código em C / C ++,
#ifdef __unix
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL
#endif
Em Makefile
CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL'
Atenção que na fopen_s sucesso retornar 0 enquanto o retorno fopen um ponteiro de arquivo diferente de zero. Por isso, é necessário adicionar "== null" para o fim da macro, por exemplo:.
if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
Muitas das funções seguras da Microsoft estão incluídas no anexo K do padrão C11, mas não é amplamente apoiada, de modo a portabilidade ainda é um problema. Há uma necessidade para a melhoria da segurança em algumas aplicações; talvez o apoio vai melhorar no futuro.
I passado, eu fiz assim:
#define fopen_s(fp, fmt, mode) *(fp)=fopen( (fmt), (mode))
A macro é simples e direta, bom o suficiente para uma rápida algo e sujo, mas não fornece o comportamento exceção de fopen_s, e que não irá fornecer a segurança da função fopen_s real.
abordagem da função de @Alex B acima parcialmente reproduz o comportamento adequado em caso de falha; ele retorna errno (= EINVAL). Sua abordagem pode ser estendido ainda mais, gerando um parâmetro inválido exceção para reproduzir mais plenamente o comportamento de fopen_s.
#define fopen_s(fp, fmt, mode) ({\
*(fp)=fopen( (fmt), (mode));\
(*(fp) ) ? 0:errno;\
})
Accroding para https://en.cppreference.com/w/c/io / fopen é possível habilitar * _s funções na biblioteca padrão:
Tal como acontece com todas as funções Bounds-verificados,
fopen_s
só é garantido para estar disponível se__STDC_LIB_EXT1__
é definida pela implementação e se os define usuário__STDC_WANT_LIB_EXT1__
para o inteiro constante1
antes de incluir<stdio.h>
.