2016-02-17 15 views
8

Ho scritto un piccolo programma per decodificare un file crittografato OTP. Questo funziona bene.Perché fopen funziona senza salvare il puntatore restituito?

Ma ho capito che ho dimenticato di salvare il puntatore del file restituito quando chiama fopen su "Solution.jpg". Come puoi vedere, sto scrivendo sul puntatore del file f. Mi chiedo perché questo codice funzioni.

#include <stdio.h> 

#define FILE_SIZE 4202 

int main() { 
    unsigned char key[FILE_SIZE], otpCipher[FILE_SIZE]; 

    FILE *f = fopen("otpkey.bin", "r"); 
    fread(key, sizeof(char), FILE_SIZE, f); 
    fclose(f); 

    f = fopen("otpcipher.bin", "r"); 
    fread(otpCipher, sizeof(char), FILE_SIZE, f); 
    fclose(f); 

    fopen("Solution.jpg", "w"); 

    for (int j = 0; j < FILE_SIZE; ++j) { 
     otpCipher[j] = otpCipher[j]^key[j]; 
     fputc(otpCipher[j], f); 
    } 

    fclose(f); 

    return 0; 
} 
+1

'f' non è valido dopo la chiusura. Quindi usarlo in qualsiasi altra funzione dopo questo è un comportamento indefinito. UB significa che potrebbe funzionare ma potrebbe anche bloccarsi, o scrivere in qualche altro file, o continuare in silenzio, o qualsiasi altra azione indefinita. – kaylum

+0

È 'fputc (otpCipher [j], f);' scrive in 'Solution.jpg'? Io non la penso così ... – LPs

+3

@LPs Penso che faccia nel caso dell'OP. Perché 'fopen (" Solution.jpg "," w ");' capita di riutilizzare la stessa memoria per quel 'FILE' come il puntatore' f' già fa riferimento. Quindi il puntatore in 'f' usato per quel' fputc' è valido per caso. – kaylum

risposta

6

Ho appena trovato la risposta utilizzando gdb.

Quindi, poiché sto utilizzando fclose() prima di aprire il nuovo file, il puntatore del file utilizzato in precedenza è stato liberato. Questo puntatore potrebbe essere utilizzato nuovamente e fopen() ha restituito questo puntatore ogni volta che eseguivo questo programma.

Quindi ha funzionato solo perché non c'erano altri file aperti nel momento in cui ho chiamato fopen().

Questo comportamento non è definito e può portare ad altri problemi. Dovrebbe essere evitato in tutte le circostanze (l'ho fatto per errore). Volevo solo capire perché questo funzionava e ho risolto il mio codice.

+4

Hai diagnosticato correttamente il comportamento effettivo, ma tieni presente che non è in alcun modo giustificato dallo standard C. È un comportamento indefinito usare 'f' dopo aver chiamato' fclose (f) '. Chiamalo un piccolo miracolo che 'fopen()' restituisca lo stesso puntatore, certamente non fare affidamento su di esso. Nota inoltre che dovresti anche controllare i valori di ritorno di 'fopen' e' fread'. – chqrlie

+0

Grazie, so che questa è una brutta cosa. Quindi ho aggiunto questo alla mia risposta per motivi di chiarezza. – johnson262

+4

+1 sia per esplorare il problema da soli usando gdb e rendersi conto che accettare che "capita di lavorare" non è un buon stato. – TripeHound

Problemi correlati