Y at-il un moyen d'utiliser fopen_s () avec GCC ou au moins créer un #define à ce sujet?
-
19-09-2019 - |
Question
compilateur MSVC dit que fopen()
est dépréciée, et recommande l'utilisation de fopen_s()
.
Est-il possible d'utiliser fopen_s()
et encore portable?
Des idées pour un #define
?
La solution
Les fonctions de *_s
de Microsoft sont non portable, je l'habitude d'utiliser des fonctions équivalentes C89 / C99 et désactiver les avertissements relatifs à l'obsolescence (#define _CRT_SECURE_NO_DEPRECATE
).
Si vous insistez, vous pouvez utiliser une fonction d'adaptation (pas nécessairement une macro!) Que les délégués fopen()
sur les plates-formes qui ne sont pas fopen_s()
, mais vous devez faire attention à la carte des valeurs de code errno_t
retour 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;
}
Cependant, je ne vois pas comment fopen_s()
est plus sûr que fopen()
, donc je vais habituellement pour la portabilité.
Autres conseils
si vous utilisez C11, fopen_s
est une bibliothèque standard:
http://en.cppreference.com/w/c/io/fopen
gcc
vous devez utiliser le paramètre de --std=C11
.
Dans le code C / C ++,
#ifdef __unix
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL
#endif
Dans Makefile
CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL'
Attention, que le succès fopen_s retour 0 en retour fopen un pointeur de fichier non nul. Par conséquent, il est nécessaire d'ajouter « == NULL » à la fin de la macro, par exemple:.
if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
La plupart des fonctions sécurisées de Microsoft figurent à l'annexe K de la norme C11, mais il est pas largement pris en charge, si la portabilité est toujours un problème. Il est nécessaire pour l'amélioration de la sécurité dans certaines applications; peut-être le soutien permettra d'améliorer à l'avenir.
Je le passé, je l'ai fait comme ceci:
#define fopen_s(fp, fmt, mode) *(fp)=fopen( (fmt), (mode))
La macro est simple et simple, assez bon pour quelque chose de rapide et sale, mais il ne fournit pas le comportement d'exception de fopen_s, et il ne fournira pas la sécurité de la fonction réelle de fopen_s.
L'approche de la fonction de B ci-dessus reproduit @ Alex partiellement le bon comportement en cas d'échec; il retourne errno (= EINVAL). Son approche pourrait être élargie en générant un exception de paramètre non valide à reproduire plus complètement le comportement de fopen_s.
#define fopen_s(fp, fmt, mode) ({\
*(fp)=fopen( (fmt), (mode));\
(*(fp) ) ? 0:errno;\
})
https://en.cppreference.com/w/c/io / fopen il est possible d'activer * _S fonctions de la bibliothèque standard:
Comme avec toutes les fonctions hors limites vérifiées,
fopen_s
est uniquement assuré d'être disponible si__STDC_LIB_EXT1__
est définie par la mise en oeuvre et si l'utilisateur définit__STDC_WANT_LIB_EXT1__
à l'entier1
constante avant d'inclure<stdio.h>
.