2011-01-26 24 views
41

Eventuali duplicati:
Do I need to manually close a ifstream?ho bisogno di chiudere uno std :: fstream?

Devo chiamare fstream.close() o è fstream un oggetto RAII corretta che chiude il flusso sulla distruzione?

Ho un oggetto locale std::ofstream all'interno di un metodo. Posso presumere che il file sia sempre chiuso dopo essere uscito da questo metodo senza chiamare close? Non sono riuscito a trovare la documentazione del distruttore.

+0

sì, è un duplicato. Grazie. Non l'ho trovato. –

+3

Non è un duplicato esatto. La domanda di riferimento è specifica per ifstreams e questa è in genere relativa a fliche. –

risposta

65

Penso che le risposte precedenti siano fuorvianti.

fstreamè un oggetto Raii adeguata, fa chiudere automaticamente alla fine del campo di applicazione, e non v'è assolutamente alcun bisogno chiamare close manualmente quando si chiude alla fine della portata è sufficiente.

In particolare, non è una "best practice" e non è necessario svuotare l'output.

E mentre Drakosha ha ragione che chiamare close ti dà la possibilità di controllare il bit di fail del flusso, nessuno lo fa, comunque.

In un mondo ideale, è sufficiente chiamare in anticipo stream.exception(ios::failbit) e gestire l'eccezione che viene generata nel distruttore di fstream. Ma sfortunatamente le eccezioni nei distruttori sono un concetto rotto in C++, quindi non è una buona idea.

Quindi se si desidera verificare il successo della chiusura di un file, farlo manualmente (ma solo successivamente).

+4

Controllo effettivamente i risultati ravvicinati ogni volta, perché sto lavorando a un'applicazione che deve garantire che i dati vengano trasferiti sul disco. Inoltre, un po 'fuori punto, ** chiudi non garantisce lo svuotamento ** (su Linux almeno), e non sono sicuro che il distruttore si svuota. In realtà, direi che è "best practice" chiudere e chiudere e controllare gli errori su entrambi. – Drakosha

+7

@Drakosha: assicurarsi che i dati vengano scaricati fino al disco è una cosa completamente diversa da ciò che garantisce "flush" o "close". Il meglio che si può assumere in generale è che "flush" preleva i dati dal processo e nel livello del sistema operativo, quindi ad es. uccidere il processo non impedirà la scrittura dei dati. Non esiste un'API portatile per garantire che i dati vengano trasferiti alla memoria persistente, poiché lo standard C++ non ha alcun concetto di archiviazione persistente rispetto ad altri archivi presentati come (parte di) un filesystem. –

+1

Sono anche un po 'sorpreso dal comportamento di Linux. Il distruttore fstream è richiesto per chiamare la funzione membro 'close',' close' è necessario per chiudere "come se fosse' fclose' ", e' fclose' è definito per svuotare il flusso. Quindi il distruttore dovrebbe certamente svuotare, anche se lo svuotamento potrebbe non necessariamente fare quello che vuoi se c'è il rischio che la spina venga tirata sulla macchina. Per questo è necessario (non standard-C++) 'fsync'. –

1

penso che sia una buona pratica di chiudere il fstream, perché è necessario svuotare il buffer, che quello che mi è stato detto

+5

se fstream è un oggetto RAII, verrà chiuso e quindi i buffer saranno comunque scaricati. La domanda principale è se ho bisogno di una gestione degli errori su tutti i flussi di controllo per assicurarmi che venga svuotata. –

+4

Siamo spiacenti, -1 solo perché in qualche modo aveva +2. Rilasciare manualmente una risorsa è un segno di programmazione errata o un fraintendimento dello scopo di un contenitore. – GManNickG

+0

@GMan: Direi che non ti preoccupare se il tuo file è chiuso correttamente è il caso eccezionale, e dovresti chiamare 'close()' te stesso nella maggior parte delle situazioni. * Troppo * troppi sviluppatori di software fanno supposizioni che preferirei non riguardassero l'affidabilità e la disponibilità dei filesystem dell'utente. –

6

Per aggiungere alla risposta di Amy Lee, è meglio farlo manualmente perché in questo modo puoi anche controllare gli errori

proposito, secondo "close" manpage:

Non verificare il valore restituito close() è un comune, ma comunque serio errore di programmazione. È abbastanza possibile che gli errori su una precedente operazione scrittura (2) vengano segnalati per la prima volta allo alla chiusura finale(). La mancata verifica del valore di ritorno durante la chiusura del file potrebbe causare la perdita di dati. Ciò può essere osservato in particolare con NFS e con quota disco.

Un successo stretta non garantisce che i dati è stato con successo salvati su disco, come il kernel rinvia scrive. Non è comune per un file system svuotare i buffer quando lo stream viene chiuso. Se hai bisogno di assicurati che i dati siano fisicamente memorizzati usa fsync (2). (A questo punto dipenderà da sull'hardware del disco.)

+1

È meglio farlo manualmente * se * è necessario verificare la presenza di errori, ciò non significa che dovremmo * sempre * chiudere manualmente. Non puoi fare una pratica generale per un caso eccezionale. Nel caso generale, quando si sta chiudendo non ci interessa come ci sia riuscito, quindi lasciamolo andare automaticamente. – GManNickG

+3

@GMan: se non si verificano errori, significa che si sta fuorviando l'utente che i dati sono sul disco mentre non lo è. – Drakosha

+1

@Drakisha: Ma come dice Steve, una volta che chiudo (che viene eseguito automaticamente), l'errore o meno è fuori dalle mie mani. Anche il tuo "potenziamento" è C++ non standard, stiamo parlando del C++ 'fstream' standard qui. – GManNickG