GNU/Linux >> Linux の 問題 >  >> Linux

hexdump が EOF を読み込もうとするのはなぜですか?

ヒントをくれた @JdeBP のおかげで、hexdump と同じことを行う小さなテストケースを作成できました。 :

#include <stdio.h>

int main(void){
        char buf[64]; size_t r;
        for(;;){
                printf("eof=%d, error=%d\n", feof(stdin), ferror(stdin));
                r = fread(buf, 1, sizeof buf, stdin);
                printf("read %zd bytes, eof=%d, error=%d\n",
                        r, feof(stdin), ferror(stdin));
                if(!r) return 0;
        }
}

glibc ベースのシステム (典型的な Linux デスクトップ) で実行する場合。

prompt$ ./fread-test
eof=0, error=0
<control-D>
read 0 bytes, eof=1, error=0

prompt$ ./fread-test
eof=0, error=0
hello
<control-D>
read 6 bytes, eof=1, error=0
eof=1, error=0
<control-D>
read 0 bytes, eof=1, error=0

bsd、solaris、busybox (uclibc)、android などで実行する場合:

prompt$ ./fread-test
eof=0, error=0
hello
<control-D>
read 6 bytes, eof=1, error=0
eof=1, error=0
read 0 bytes, eof=1, error=0

標準の私の不慣れな解釈に基づくと、これはバグのように見えます glibc (GNU C ライブラリ) で。

fread について :

<ブロック引用>

オブジェクトごとに、サイズの呼び出しが fgetc() 関数に対して行われ、その結果が、オブジェクトを正確にオーバーレイする unsigned char の配列に read の順序で格納されます。

fgetc について :

<ブロック引用>

bystream を指す入力ストリームのファイル終了インジケータが設定されていない場合 次のバイトが存在する場合、fgetc() 関数は次のバイトを取得します

eof インジケータが設定されていても、glibc は「次のバイトを取得」しようとするようです。

確かに、実際に GNU C ライブラリのバグであり、BSD または musl C ライブラリには存在しません。これは 2005 年に知られていました。Ulrich Drepper は 2007 年にバグを修正せずにバグ レポートを閉じました。2012 年に議論され、他の C ライブラリにはこの動作がなく、また、1999 年の C 標準はかなりそれについて具体的であり、Solaris には、c99 のときに呼び出されるこのための特別なメカニズムさえあります。 cc の代わりにコンパイラとして使用されます .

2018 年に最終的に修正されました。修正は GNU C ライブラリのバージョン 2.28 にあります。 Debian の現在の「安定した」バージョンであるバージョン 9 は、GNU C ライブラリのバージョン 2.24 にあり、このバグは報告されてから 14 年経っても現れ続けています。

GNU C ライブラリの議論で述べたように、可能性があります。 musl などの他の C ライブラリや他のプラットフォームでの動作に関係なく、GNU C ライブラリの癖を必要とするように作成されたソフトウェアのことです。しかし、前述の何年にもわたる議論では、そのようなプログラムは特定されませんでした。古い GNU C ライブラリによって破損しているいくつかのプログラムでは、ユーザーに 2 回連続して EOF を通知する必要があるため、 特定された;とりわけ hexdump を含む ここと patch 2018 年に StackOverflow で。


Linux
  1. なぜ男は00:30に「gimmeGimmeGimme」を印刷するのですか?

  2. `while Ifs =Read ..`で、なぜIfsは効果がないのですか?

  3. Linux –Setuidが機能しないのはなぜですか??

  1. Ssh -tオプションがリダイレクト出力にCrとLfを追加するのはなぜですか?

  2. 移動の許可が拒否された場合、Mv(1)がオブジェクトをコピーするのはなぜですか?

  3. Unix時間が1970-01-01から始まるのはなぜですか?

  1. これが「読み取り中」にターミナルで機能するのに、シェルスクリプトでは機能しないのはなぜですか?

  2. なぜ`exit&`が機能しないのですか?

  3. 「/」に「..」エントリがあるのはなぜですか?