¿Hay una manera de utilizar fopen_s () con GCC o al menos crear un #define respecto?
-
19-09-2019 - |
Pregunta
MSVC compilador dice que fopen()
está en desuso, y recomienda el uso de fopen_s()
.
¿Hay alguna manera de utilizar fopen_s()
y todavía ser portátil?
¿Alguna idea para un #define
?
Solución
*_s
funciones de Microsoft son no portables, que suelen utilizar las funciones C89 / C99 equivalentes y desactivar las advertencias de obsolescencia (#define _CRT_SECURE_NO_DEPRECATE
).
Si insiste, se puede utilizar una función de adaptador (no necesariamente una macro!) Que los delegados fopen()
en plataformas que no tienen fopen_s()
, pero hay que tener cuidado al asignar los valores de código de retorno de 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;
}
Sin embargo, no veo cómo fopen_s()
es más segura que la fopen()
, así que suelo ir para la portabilidad.
Otros consejos
si está utilizando C11, fopen_s
es una biblioteca estándar:
http://en.cppreference.com/w/c/io/fopen
en gcc
es necesario utilizar el parámetro --std=C11
.
En código C / C ++,
#ifdef __unix
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL
#endif
En Makefile
CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL'
La atención de que en caso de éxito fopen_s devolver 0, mientras que fopen devuelve un puntero a un archivo distinto de cero. Por lo tanto es necesario añadir "== NULL" al final de macro, por ejemplo:.
if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
Muchas de las funciones de seguridad de Microsoft están incluidas en el Anexo K de la norma C11, pero no se admite ampliamente, por lo que la portabilidad sigue siendo un problema. Hay una necesidad para la mejora de la seguridad en algunas aplicaciones; tal vez el apoyo mejorará en el futuro.
Yo el pasado, lo hice de esta manera:
#define fopen_s(fp, fmt, mode) *(fp)=fopen( (fmt), (mode))
La macro es simple y sencillo, lo suficientemente bueno para algo rápido y sucio, pero no proporciona el comportamiento excepción de fopen_s, y no va a proporcionar la seguridad de la función fopen_s real.
enfoque de la función de @Alex B anterior parcialmente reproduce el comportamiento adecuado en caso de fallo; regresa errno (= EINVAL). Su enfoque podría ampliarse aún más mediante la generación de un excepción parámetro no válido para reproducir mejor el comportamiento de fopen_s.
#define fopen_s(fp, fmt, mode) ({\
*(fp)=fopen( (fmt), (mode));\
(*(fp) ) ? 0:errno;\
})
https://en.cppreference.com/w/c/io / fopen es posible habilitar * _S funciones de la biblioteca estándar:
Al igual que con todas las funciones grada-controladas,
fopen_s
sólo se garantiza que esté disponible si__STDC_LIB_EXT1__
se define por la aplicación y si el usuario define__STDC_WANT_LIB_EXT1__
al entero1
constante antes de incluir<stdio.h>
.