2010-04-04 26 views
19

Sto usando fopen in C per scrivere l'output in un file di testo. La dichiarazione di funzione è (dove ARRAY_SIZE è stato definito in precedenza):fopen/fopen_s e scrittura su file

void create_out_file(char file_name[],long double *z1){ 
    FILE *out; 
    int i; 

    if((out = fopen(file_name, "w+")) == NULL){ 
    fprintf(stderr, "***> Open error on output file %s", file_name); 
    exit(-1); 
    } 

    for(i = 0; i < ARRAY_SIZE; i++) 
    fprintf(out, "%.16Le\n", z1[i]); 
    fclose(out); 
} 

Le mie domande:

  1. Sulla compilation con MVS2008 ottengo l'avvertimento: avviso C4996: 'fopen': questa funzione o variabile potrebbe essere pericoloso Prendi in considerazione l'utilizzo di fopen_s. Non ho visto molte informazioni su fopen_s in modo che possa cambiare il mio codice. Eventuali suggerimenti?

  2. Si può ordinare fprintf di scrivere numeri con una precisione numerica desiderata in un file? Se sto usando long double allora presumo che le mie risposte siano valide fino a 15 cifre dopo il punto decimale. Ho ragione?

+16

Non c'è nulla di lontanamente pericoloso su fopen(), ma alcune persone in MS sembrano aver perso le loro biglie collettive su funzioni che accettano stringhe con terminazione nulla come parametri. –

+0

Credo che questo sia tutto un complotto di Microsoft per bloccare le persone nella programmazione solo per Windows. – stackptr

risposta

16

fopen_s è una variante del fopen che contiene la convalida dei parametri e le mani di nuovo un codice di errore al posto di un puntatore nel caso qualcosa vada storto durante il processo aperto. È più sicuro della variante di base perché rappresenta più condizioni di bordo. Il compilatore ti avverte di usarlo perché fopen rappresenta un potenziale vettore di sfruttamento nella tua applicazione.

È possibile specificare cifre di precisione al printf famiglia di funzioni utilizzando l'identificatore %.xg, dove x è il cifre di precisione che si desidera in uscita. A long double varia in precisione da una piattaforma all'altra, ma generalmente si può scommettere su di esso con almeno 16 cifre di precisione decimale.

Edit: Mentre io non sono del tutto a bordo con gli altri che stanno suggerendo che fopen_s è uno spreco completa di tempo, essa rappresenta una bella bassa probabilità di sfruttamento e non è ampiamente supportato. Alcune delle altre funzioni avvertite in merito a C4996 sono vulnerabilità molto più gravi, tuttavia, e l'utilizzo di _CRT_SECURE_NO_WARNINGS equivale a disattivare l'allarme per entrambi "hai lasciato la porta della camera da letto sbloccata" e "hai lasciato una bomba nucleare in cucina".

Purché non si limiti a utilizzare "C pura" per il progetto (ad es.per un incarico scolastico o un microcontrollore integrato, faresti bene a sfruttare il fatto che quasi tutti i compilatori C moderni sono anche compilatori C++ e utilizzano le varianti C++ iostream di tutte queste funzioni I/O per ottenere una maggiore sicurezza e la compatibilità allo stesso tempo.

+0

Grazie. Ho fprintf (out, "% .16Le \ n", z1 [i]) nel mio codice e sì ottengo le 16 cifre di precisione dopo il d.p. – yCalleecharan

+0

Grazie ancora. Sto usando C come questo è quello che so meglio. Sto scrivendo un codice per scopi di ricerca che deve dare risultati precisi. Ho dovuto non dimensionare le mie equazioni formando il codice C in modo da avere un buon intervallo di valori che impedirebbe valori troppo grandi o valori troppo bassi per insinuarsi nella simulazione e quindi nella soluzione. Non so molto di C++ e non so se posso salvare il mio file in cpp e usare C++ iostream in modo sicuro senza altre parti del mio codice che mi danno errori di compilazione. Per ora, mi limiterò a C finché non saprò come passare a C++. – yCalleecharan

1

Basta definire _CRT_SECURE_NO_WARNINGS prima di includere qualsiasi tipo di file per sbarazzarsi di queste avvertenze, e smettere di credere a ciò che MS dice circa fopen

+0

Grazie. È solo per aggiungere #define _CRT_SECURE_NO_WARNINGS in alto? – yCalleecharan

6
  1. fopen_s e tutte le altre _s funzioni sono MS-specifico " sicuro "varianti di funzioni standard. Se il tuo codice non ha bisogno di essere multipiattaforma, puoi semplicemente cambiare e rendere felice il compilatore. Altrimenti, aggiungi la direttiva preposizionatore _CRT_SECURE_NO_WARNINGS alle impostazioni del tuo progetto e smetterà di avvertirti.

  2. Sì, il doppio lungo è facilmente valido per 15 cifre di precisione; in realtà, anche i doppi regolari sono abbastanza buoni per questo (ma non di più).

+0

Grazie. Sulla mia macchina a 32 bit, sia il doppio che il doppio lungo mi dà 16 cifre di precisione e la 16a cifra è quella non accurata. – yCalleecharan

+0

Sì, la dimensione 'lunga doppia 'dipende dalla piattaforma; purtroppo, MSVC++ lo rende lo stesso di 'double', quindi non serve davvero. Una doppia 64 bit ha una precisione di 53 bit nella mantissa, che è circa 15,95 cifre decimali (log10 (53)). – tzaman

+0

Grazie per le informazioni. – yCalleecharan

4

Altri poster hanno sottolineato che fopen non è davvero molto pericoloso. Se non si desidera questo avviso, ma si desidera che gli altri avvisino di vulnerabilità reali, non #define _CRT_SECURE_NO_WARNINGS.

Invece, la prossima volta che si ottiene l'avviso di fopen, fare clic sulla riga che dice "vedere la dichiarazione di 'fopen'". Questo ti porterà alla riga in stdio.h che sta iniettando l'avviso. Eliminare il testo _CRT_INSECURE_DEPRECATE(fopen_s) da quella riga e non verrà più visualizzato l'avviso di sicurezza quando si utilizza fopen, ma rimarrà per strcpy, strdup e altri potenzialmente pericolosi.

+1

in realtà su Windows l'implementazione "standard" di open ha alcune vulnerabilità dovute ai marmocchi 14, 125, 16 anni che non hanno niente di meglio da fare con il loro tempo di trovare modi per hackerare programmi e rovinare i computer di altre persone, quindi è venuto fuori con un modo diverso per passare il descrittore di file rendendolo più difficile per gli adolescenti – BrierMay

8

Mi sono imbattuto in un problema simile a quello di Visual Studio 2012, ma il mio problema è stato ampliato mentre sto costruendo un programma che voglio utilizzare i campanelli di Visual Studio per i test e alla fine poter compilare ed eseguire stessa applicazione sul mio server Linux (sto facendo un bot)

quindi questo è quello che mi è venuto in mente dopo un po 'di Google-ing e ho pensato di pubblicarlo nel caso in cui potrebbe aiutare qualcun altro.

FILE *fp_config; 
const char *configfile ; 
configfile = "bot.conf"; 
#ifdef WIN32 
    errno_t err; 
    if((err = fopen_s(&fp_config, configfile, "r")) !=0) { 
#else 
    if ((fp_config = fopen(configfile, "r")) == NULL) { 
#endif 
     fprintf(stderr, "Cannot open config file %s!\n", configfile); 
    } 

questo placherà Visual Studio e non si lamentano e permetterà anche lo stesso codice per compilare il gcc o qualsiasi altro standard di C/C++ compiler

4

compatibile Passando da fopen al fopen_s disabilitato la capacità per aprire il file nel blocco note (sola lettura) mentre il file è aperto e in fase di scrittura. Tornando indietro a fopen e posso leggere wile il mio programma scrive il file.

+0

Dal [riferimento] (http://en.cppreference.com/w/c/io/fopen): Quando si utilizza fopen_s o freopen_s, file le autorizzazioni di accesso per qualsiasi file creato con "w" o "a" impediscono ad altri utenti di accedervi.L'opzione "u" per l'accesso ai file può essere anteposta a qualsiasi identificatore che inizia con "w" o "a", per abilitare le autorizzazioni fopen predefinite. (C11) –