2016-02-17 21 views
8

Napisałem mały program do odszyfrowania zaszyfrowanego pliku OTP. Działa to dobrze.Dlaczego fopen działa bez zapisywania zwróconego wskaźnika?

Ale zdałem sobie sprawę, że zapomniałem zapisać zwrócony wskaźnik pliku podczas wywoływania fopen na "Solution.jpg". Jak widać, piszę do wskaźnika pliku f. Zastanawiam się, dlaczego ten kod działa.

#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' jest nieprawidłowe po zamknięciu. Używanie go w dowolnej innej funkcji jest niezdefiniowanym zachowaniem. UB oznacza, że ​​może działać, ale może również ulec awarii, lub napisać do jakiegoś innego pliku lub kontynuować dyskretnie lub dowolną inną niezdefiniowaną akcję. – kaylum

+0

Czy 'fputc (otpCipher [j], f);' pisze do 'Solution.jpg'? Nie sądzę ... – LPs

+3

@LPs Myślę, że tak jest w przypadku OP. Ponieważ 'fopen (" Solution.jpg "," w ");' po prostu używa ponownie tej samej pamięci dla tego 'PLIKU ', ponieważ wskaźnik' f' już wskazuje. Zatem wskaźnik w 'f' używany dla tego' fputc' jest poprawny przez przypadek. – kaylum

Odpowiedz

6

Właśnie znalazłem odpowiedź za pomocą gdb.

Ponieważ używam fclose() przed otwarciem nowego pliku, wskaźnik do pliku używanego wcześniej został zwolniony. Ten wskaźnik może zostać użyty ponownie i fopen() zwróciło ten wskaźnik za każdym razem, gdy uruchomiłem ten program.

Tak więc zadziałało tylko dlatego, że nie było innego pliku otwartego w czasie, gdy zadzwoniłem pod numer fopen().

Jest to niezdefiniowane zachowanie, które może prowadzić do innych problemów. Należy tego unikać w każdych okolicznościach (zrobiłem to przez pomyłkę). Chciałem tylko zrozumieć, dlaczego to działa i naprawiłem mój kod.

+4

Prawidłowo zdiagnozowano rzeczywiste zachowanie, ale pamiętaj, że nie jest on w żaden sposób akceptowany przez standard C. Niezdefiniowanym zachowaniem jest użycie 'f' po wywołaniu' fclose (f) '. Nazwijmy to małym cudem, że 'fopen()' zwraca tę samą wskazówkę, na pewno nie polegamy na tym. Zwróć też uwagę, że powinieneś również sprawdzić wartości zwracane przez 'fopen' i' fread'. – chqrlie

+0

Dziękuję, wiem, że to jest złe. Dlatego dodałem to do mojej odpowiedzi ze względu na jasność. – johnson262

+4

+1 dla odkrywania problemu samemu za pomocą gdb i realizowania/akceptowania, że ​​"zdarza się, że działa" nie jest dobrym stanem. – TripeHound

Powiązane problemy