Perché non posso usare fopen?
-
05-09-2019 - |
Domanda
Nello stampo di una domanda precedente che ho posto sulle cosiddette deprecazioni delle librerie sicure, Mi ritrovo altrettanto confuso sul perché fopen()
dovrebbe essere deprecato.
La funzione accetta due stringhe C e restituisce un FILE* ptr o NULL in caso di errore.Dove sono i problemi di sicurezza del thread/problemi di sovraccarico delle stringhe?O è qualcos'altro?
grazie in anticipo
Soluzione
C'è un ufficiale ISO / IEC JTC1 / SC22 / WG14 (C Language) relazione tecnica TR24731-1 (il controllo dei limiti interfacce) e la sua logica disponibile all'indirizzo:
C'è anche lavorare per TR24731-2 (funzioni di allocazione dinamica).
Il razionale ultimo per fopen_s()
è:
funzioni di accesso6.5.2 File
Quando si crea un file, le funzioni e
fopen_s
freopen_s
migliorare la sicurezza proteggendo il file da accessi non autorizzati impostando la protezione dei file e aprire il file con accesso esclusivo.
La specifica dice:
6.5.2.1 La funzione fopen_s
Sinossi
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
errno_t fopen_s(FILE * restrict * restrict streamptr,
const char * restrict filename,
const char * restrict mode);
Runtime-vincoli
Nessuno di streamptr
, filename
, o mode
deve essere un puntatore nullo.
Se c'è una violazione di runtime-constraint, fopen_s
non tenta di aprire un file.
Inoltre, se streamptr
non è un puntatore nullo, insiemi fopen_s
*streamptr
al
puntatore nullo.
Descrizione
La funzione
fopen_s
apre il file il cui nome è la stringa puntata dafilename
, e associa un ruscello con esso.La stringa modalità è come descritto per
fopen
, con l'aggiunta che Modalità partenza con il carattere ‘w’ o ‘a’ può essere preceduto dal carattere ‘u’, vedere sotto:
uw
troncato a lunghezza zero o creare file di testo per la scrittura, permessi di defaultua
append; aprire o creare file di testo per la scrittura alla fine del file, permessi di defaultuwb
troncato a lunghezza zero o creare file binario per la scrittura, permessi di defaultuab
append; aprire o creare file binario per la scrittura alla fine del file, di default permessiuw+
troncato a lunghezza zero o creare file di testo per l'aggiornamento, permessi di defaultua+
append; aprire o creare file di testo per l'aggiornamento, la scrittura alla fine del file, di default permessiuw+b
ouwb+
troncano a lunghezza zero o creare file binario per l'aggiornamento, di default permessiua+b
ouab+
accodamento; aprire o creare file binario per l'aggiornamento, la scrittura alla fine del file, autorizzazioni predefiniteNella misura in cui il sistema sottostante supporta i concetti, i file aperti per la scrittura vengono aperti esclusivo (noto anche come non comune). Se il file viene creato e il primo carattere della stringa modalità non è ‘u’, nella misura in cui la sistema sottostante lo supporta, il file deve avere un permesso di file che impedisce ad altri gli utenti del sistema di accedere al file. Se viene creato il file e il primo carattere della modalità stringa è ‘u’, quindi per il momento il file è stato chiuso, esso deve avere la autorizzazioni di accesso file system predefinito 10) .
Se il file è stato aperto con successo, allora il puntatore
FILE
puntato dastreamptr
sarà impostato al puntatore all'oggetto che controlla il file aperto. In caso contrario, il puntatore aFILE
puntata dastreamptr
sarà impostato un puntatore nullo.I ritorni
La funzione
fopen_s
restituisce zero se si apre il file. Se non aprire il file o se c'è stata una violazione di runtime-constraint,fopen_s
restituisce un valore diverso da zero.10) Queste sono le stesse autorizzazioni che il file sarebbe stato creati con da fopen.
Altri suggerimenti
possono uso fopen()
. Scherzi a parte, non prendere alcun avviso di Microsoft qui, che stanno facendo i programmatori un vero e proprio disservizio deviando dagli standard ISO. Sembrano pensare che le persone che scrivono il codice sono in qualche modo morte cerebrale e non sanno come controllare i parametri prima di chiamare le funzioni di libreria.
Se qualcuno non è disposto ad imparare la complessità di programmazione C, in realtà non hanno nessun business farlo. Essi dovrebbero passare a una lingua più sicura.
Questo sembra essere solo un altro tentativo di vendor lock-in da parte di Microsoft di sviluppatori (anche se non sono gli unici che cercano di esso, quindi non mi specificamente li berating). Io di solito aggiungere:
#define _CRT_SECURE_NO_WARNINGS
(o la variante "-D"
sulla riga di comando) per la maggior parte dei miei progetti per assicurare che non sono infastidito dal compilatore durante la scrittura perfettamente valido, il codice C legale.
Microsoft ha fornito funzionalità aggiuntive nella funzione fopen_s()
(codifiche dei file, per uno) così come cambiare come le cose vengono restituiti. Ciò può rendere meglio per i programmatori di Windows, ma rende il codice intrinsecamente portabile.
Se avete sempre e solo andando a codice per Windows, con tutti i mezzi lo usano. Io preferisco la possibilità di compilare ed eseguire il mio codice da nessuna parte (con un minimo cambiamento possibile).
A partire dal C11, queste funzioni di sicurezza sono ora una parte dello standard, anche se opzionale. Se vuoi in allegato K per tutti i dettagli.
IL fopen_s()
è stata aggiunta da Microsoft al runtime C con le seguenti differenze fondamentali rispetto a fopen()
:
- se il file viene aperto in scrittura ("w" o "a" specificato nella modalità) allora il file viene aperto in accesso esclusivo (non condiviso) (se la piattaforma lo supporta).
- se l'identificatore "u" viene utilizzato nell'argomento mode con gli specificatori "w" o "a", quando il file verrà chiuso, avrà i permessi predefiniti del sistema per consentire ad altri utenti di accedere al file (che potrebbe non essere accesso se questa è l'impostazione predefinita del sistema).
- se la "u" specificata lo è non utilizzato in questi casi, quando il file viene chiuso (o prima) le autorizzazioni per il file verranno impostate in modo tale che altri utenti non abbiano accesso al file.
In sostanza significa che i file scritti dall'applicazione sono protetti da altri utenti per impostazione predefinita.
Non hanno fatto questo fopen()
a causa della probabilità che il codice esistente si rompa.
Microsoft ha scelto di deprecare fopen()
per incoraggiare gli sviluppatori di Windows a prendere decisioni consapevoli sul fatto se i file utilizzati dalle loro applicazioni avranno o meno autorizzazioni libere.
La risposta di Jonathan Leffler fornisce il linguaggio di standardizzazione proposto per fopen_s()
.Ho aggiunto questa risposta sperando di chiarire la logica.
O è qualcos'altro?
Alcune implementazioni della struttura dei file utilizzato da 'fopen' ha il descrittore di file definito come 'unsigned short'. Questo ti lascia con un massimo di 255 file contemporaneamente aperti, meno stdin, stdout e stderr.
Mentre il valore di essere in grado di avere 255 file aperti è discutibile, naturalmente, questo dettaglio di implementazione si materializza sulla piattaforma Solaris 8 quando si hanno più di 252 presa connessioni ! Ciò che prima appariva come un fallimento apparentemente casuale di stabilire una connessione SSL utilizzando libcurl nella mia richiesta si rivelò essere causato da questo, ma ci sono voluti distribuzione di versioni di debug di libcurl e OpenSSL e intensificando il cliente attraverso lo script debugger per capire finalmente fuori.
Anche se non è del tutto colpa del 'FOPEN', si possono vedere le virtù di buttare via le catene di vecchie interfacce; la scelta di deprecate potrebbe essere basato sul dolore di mantenere la compatibilità binaria con un'implementazione antiquata.
Le nuove versioni fanno parametro convalida mentre i vecchi no.
questo SO filo per ulteriori informazioni.
la sicurezza thread. fopen()
utilizza una variabile globale, errno
, mentre la sostituzione fopen_s()
restituisce un errno_t
e prende un argomento FILE**
per memorizzare il puntatore del file.