C’è un modo per utilizzare fopen_s() con GCC o almeno creare un #define su di esso?

MSVC compilatore dice che fopen() è deprecato, e raccomanda l’uso di fopen_s().

C’è un modo per utilizzare fopen_s() e ancora portatile?

Qualche idea per un #define?

  • Un problema simile qui.
InformationsquelleAutor Shantia | 2009-10-03

 

6 Replies
  1. 28

    Microsoft *_s funzioni sono unportable, io di solito uso equivalente C89/C99 funzioni e disattivare la rimozione di avvisi (#define _CRT_SECURE_NO_DEPRECATE).

    Se si insiste, è possibile utilizzare un adattatore funzione (non necessariamente una macro!) che i delegati fopen() su piattaforme che non hanno fopen_s(), ma bisogna fare molta attenzione ai valori della mappa di errno_t codice di ritorno 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 vedo come fopen_s() è più sicuro rispetto a fopen(), così io di solito andare per la portabilità.

    • Microsoft AMA fare la loro versione delle cose. Mi chiedo perché…
    • La cosa divertente è che ormai sono parte di C11 (anche se opzionale Allegato K)
    • Molto meglio del mio (ormai ex, non è che ho bisogno di più puro di macro approccio. Il tuo approccio della funzione riproduce parzialmente il fopen_s comportamento in caso di errore, restituendo errno (= EINVAL, ovvero 22, fwiw). Si potrebbe anche generare un parametro non valido eccezione a partita fopen_s comportamento ancora più da vicino.
    • BTW, secondo questo, errno “si espande per una statico lvalue modificabile di tipo int )fino a C++11)”, e “si espande in un locale di thread lvalue modificabile di tipo int (dal C++11).” In modo che il ritorno dovrebbe essere del tipo int.
    • la cosa Divertente è che ormai sono parte di C11 di Microsoft le versioni non parte dell’Allegato K: “Microsoft Visual Studio implementa una prima versione delle Api. Tuttavia, l’implementazione è incompleta ed è conforme né alla C11 né all’originale TR 24731-1. … Come risultato delle numerose deviazioni dalle specifiche l’implementazione Microsoft non può essere considerato conforme o portatile.”
  2. 9

    se si utilizza C11, fopen_s è una libreria standard:

    http://en.cppreference.com/w/c/io/fopen

    in gcc è necessario utilizzare --std=C11 parametro.

    • Questa risposta è sbagliata. fopen_s() e di altre funzioni in Allegato K del C11 standard sono opzionali per K. 2 Ambito di applicazione comma 1: “il Presente allegato stabilisce una serie di estensioni opzionali …” Effettivamente, come 2019 solo Microsoft ha implementato Allegato K, e l’implementazione Microsoft “non può essere considerato conforme o portatile”.
    • infatti è c11 non c++11, anche il parametro da utilizzare nel gcc. quindi il tuo commento non è corretto.
    • anche se si potrebbe essere giusto, ma la domanda è chiedere direttamente a GCC di utilizzare fopen_s. quindi potrebbe non essere la soluzione universale, ma si colloca la questione, dicono che è sbagliato è troppo restrittiva, potrebbe non essere completo. Come per il linguaggio C, non è né il C ANSI è probabilmente il 100% portatile in alcuni software complessi, anche di basso livello. Così qui va di nuovo: compromesso.
    • GCC non ha mai implementato Allegato K, e non sarà mai. Alcune ragioni del perché: “votiamo contro la proposta. È controverso, probabilmente porta a buggier software, e non riflettono il consenso della comunità.”
    • C’è anche questa: “la Mia opinione è che l’Allegato K è stato un grande errore-l’ultima iterazione del comitato di cadere per le buffonate di uno “sponsor” che non ha interesse nell’attuazione degli standard e chi ha fatto nulla, ma cercare di minare il linguaggio C per gli ultimi 20+ anni”
    • Vedi anche stackoverflow.com/questions/50724726/…, tra le molte altre domande e le risposte che i problemi con l’Allegato K e la sua *_s “sicuro” funzioni. In breve, sono non-portatile e il solo implementazione di un qualsiasi utilizzo – Microsoft – non è conforme in ogni caso.

  3. 6

    In codice C/C++,

    #ifdef __unix
    #define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL
    #endif

    Nel Makefile

    CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL'

    Attenzione che in caso di successo fopen_s return 0 mentre fopen ritorno diverso da zero un puntatore a file. Pertanto, è necessario aggiungere “==NULL” alla fine di una macro, ad esempio:

    if (fopen_s(&pFile,filename,"r")) perror("cannot open file");
    • Ti sei perso la parte in cui fopen_s() restituisce errno se il fopen() non riesce.
  4. 2

    Molti di Microsoft sicuro funzioni sono incluse in Allegato K del C11 standard, ma non è ampiamente supportato, quindi la portabilità è ancora un problema. C’è una necessità per il miglioramento della sicurezza in alcune applicazioni; forse il supporto di migliorare in futuro.

    Ho passato, ho fatto così:

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

    La macro è semplice e dritto in avanti, abbastanza buono per qualcosa di veloce e sporco, ma non fornisce il comportamento dell’eccezione di fopen_s, e non fornire la sicurezza del reale fopen_s funzione.

    @Alex B approccio della funzione di cui sopra riproduce parzialmente il corretto comportamento in caso di errore; ritorna errno (= EINVAL). Il suo approccio potrebbe essere ulteriormente estesa, generando un parametro non valido eccezione per riprodurre il comportamento di fopen_s.

  5. -1
    #define fopen_s(fp, fmt, mode)  ({\
        *(fp)=fopen( (fmt), (mode));\
        (*(fp) ) ? 0:errno;\
    })
    • Grazie per questo frammento di codice, che potrebbe fornire un po ‘ limitato, a breve termine. Una spiegazione corretta potrebbe migliorare notevolmente il suo valore a lungo termine mostrando perché questa è una buona soluzione per il problema, e che sarebbe più utile per i lettori futuri con altre domande simili. modifica la tua risposta per aggiungere un po ‘ di spiegazioni, tra le ipotesi che hai fatto.
    • Basta aggiungere “({…})” sostenuto da GCC e Clang per restituire valore, in base al 2 ° piano di risposta di @riderBill. Grazie riderBill.
  6. -1

    Quale a https://en.cppreference.com/w/c/io/fopen
    è possibile attivare *_s funzioni di libreria standard:

    Come con tutti i limiti-controllato funzioni, fopen_s è garantito per essere disponibile se __STDC_LIB_EXT1__ è definita dall’applicazione e, se l’utente definisce __STDC_WANT_LIB_EXT1__ per la costante integer 1 prima <stdio.h>.

    • Come citato testo dice: questa opzione è disponibile solo se l’attuazione definisce __STDC_LIB_EXT1__. La maggior parte delle implementazioni non.

Lascia un commento