2016-02-17 7 views
8

OTPで暗号化されたファイルを解読するための小さなプログラムを作成しました。これはうまく動作します。返されたポインタを保存せずにfopenが動作するのはなぜですか?

しかし、 "Solution.jpg"でfopenを呼び出すときに、返されたファイルポインタを保存するのを忘れてしまったことに気付きました。ご覧のとおり、私はファイルポインタfに書いています。私はなぜこのコードが動作しているのだろうかと思っています。

#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'はそれを閉じた後無効です。それ以来、それを他の関数で使用すると、未定義の動作になります。 UBは動作する可能性がありますが、クラッシュしたり、別のファイルに書き込んだり、サイレントモードで続行したり、未定義のアクションを実行する可能性があります。 – kaylum

+0

'fputc(otpCipher [j]、f);' 'Solution.jpg'に書き込んでいますか?私はそうは思わない... – LPs

+3

@LPs私はOPのケースでそうだと思います。 'fopen(" Solution.jpg "、" w ");'はすでに参照されているポインタ 'f'と同じ' FILE'のために同じメモリを再利用するためです。したがって、 'fputc'のために使用される' f'のポインタは偶然に有効です。 – kaylum

答えて

6

私はgdbを使用して答えを見つけました。

新しいファイルを開く前にfclose()を使用しているので、以前に使用されたファイルへのポインタが解放されました。このポインタを再度使用することができ、このプログラムを実行するたびにfopen()がこのポインタを返しました。

これは、私がfopen()と呼んだときに他のファイルが開かれていないという理由だけで機能しました。

これは未定義の動作であり、他の問題を引き起こす可能性があります。それはすべての状況(私は間違ってそれをした)で避けるべきです。私はちょうどこれがなぜ動いていて、自分のコードを修正したのか理解したかった。

+4

実際の動作を正しく診断しましたが、C標準によってそれが決して受け入れられないことに注意してください。 'fclose(f)'を呼び出した後、 'f'を使うことは未定義の動作です。 'fopen()'が同じポインタを返すという小さな奇跡を呼び出してください。確かにそれに頼らないでください。また、 'fopen'と' fread'の戻り値もチェックすべきです。 – chqrlie

+0

ありがとう、私はこれが悪いことであることを知っています。だからわかりやすくするためにこれを私の答えに加えました。 – johnson262

+4

+1 gdbを使って問題を自分自身で調べて、 "うまくいく"ということを実現/受け入れることは、良い状態ではありません。 – TripeHound

関連する問題