C'è un modo per utilizzare fopen_s () con GCC o almeno creare un # define a questo proposito?
-
19-09-2019 - |
Domanda
MSVC compilatore dice che fopen()
è deprecato, e raccomanda l'uso di fopen_s()
.
C'è un modo per utilizzare fopen_s()
ed essere ancora portatile?
Tutte le idee per un #define
?
Soluzione
funzioni *_s
di Microsoft sono portabile, io di solito uso equivalenti funzioni C89 / C99 e disabilitare gli avvisi di deprecazione (#define _CRT_SECURE_NO_DEPRECATE
).
Se si insiste, è possibile utilizzare una funzione di adattatore (non necessariamente una macro!) Che i delegati fopen()
su piattaforme che non hanno fopen_s()
, ma è necessario fare attenzione per mappare i valori di codice di ritorno errno_t
da 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;
}
Tuttavia, non riesco a vedere come fopen_s()
è più sicuro rispetto fopen()
, così io di solito vado per la portabilità.
Altri suggerimenti
se si utilizza C11, fopen_s
è una libreria standard:
http://en.cppreference.com/w/c/io/fopen
in gcc
è necessario utilizzare il parametro --std=C11
.
Nel codice 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'
L'attenzione che in caso di successo fopen_s ritorno 0 mentre fopen restituire un puntatore di file diverso da zero. Pertanto è necessario aggiungere "== NULL" al fine della macro, per esempio:.
if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
Molte delle funzioni sicure di Microsoft sono incluse nell'allegato K dello standard C11, ma non è ampiamente supportato, quindi la portabilità è ancora un problema. V'è una necessità per il miglioramento della sicurezza in alcune applicazioni; forse il supporto sarà migliorare in futuro.
I passato, l'ho fatto in questo modo:
#define fopen_s(fp, fmt, mode) *(fp)=fopen( (fmt), (mode))
La macro è semplice e diretto, abbastanza buono per qualcosa di veloce e sporco, ma non fornisce il comportamento eccezione di fopen_s, e non fornirà la sicurezza della funzione fopen_s reale.
di @alex B approccio funzione sopra parzialmente riproduce il corretto comportamento in caso di errore; torna errno (= EINVAL). Il suo approccio potrebbe essere esteso ulteriormente generando un eccezione parametro non valido per riprodurre più pienamente il comportamento di fopen_s.
#define fopen_s(fp, fmt, mode) ({\
*(fp)=fopen( (fmt), (mode));\
(*(fp) ) ? 0:errno;\
})
https://en.cppreference.com/w/c/io / fopen è possibile abilitare * _S funzioni della libreria standard:
Come per tutte le funzioni di controllo dei limiti,
fopen_s
è garantita solo essere disponibile se__STDC_LIB_EXT1__
è definito dalla attuazione e se l'utente definisce__STDC_WANT_LIB_EXT1__
alla costante intera1
prima di includere<stdio.h>
.