GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Warum versucht Hexdump, EOF zu lesen?

Dank @JdeBP für den Hinweis konnte ich einen kleinen Testfall erstellen, der dasselbe tut wie 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;
        }
}

Bei Ausführung auf einem glibc-basierten System (typischer Linux-Desktop).

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

Bei Ausführung auf BSD, Solaris, Busybox (uclibc), Android usw.:

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

Basierend auf meiner unfachmännischen Interpretation des Standards sieht dies wie ein Fehler aus in glibc (der GNU-C-Bibliothek).

Über fread :

Für jedes Objekt sollen Größenaufrufe an die Funktion fgetc() erfolgen und die Ergebnisse in der gelesenen Reihenfolge in einem Array aus unsigned char gespeichert werden, das genau das Objekt überlagert.

Über fgetc :

Wenn der Dateiende-Indikator für den auf bystream zeigenden Eingabestream nicht gesetzt ist und ein nächstes Byte vorhanden ist, erhalten die fgetc()-Funktionen das nächste Byte

Es scheint, dass glibc versucht, "das nächste Byte zu erhalten", selbst wenn der eof-Indikator gesetzt ist.

Tatsächlich ist es tatsächlich ein Fehler in der GNU-C-Bibliothek, der in den BSD- oder Musl-C-Bibliotheken nicht vorhanden ist. Es war 2005 bekannt. Ulrich Drepper schloss den Fehlerbericht, ohne den Fehler 2007 zu beheben. Es wurde 2012 diskutiert, wo festgestellt wurde, dass andere C-Bibliotheken dieses Verhalten nicht hatten und haben, dass der 1999er C-Standard ziemlich ist spezifisch darüber, und dass Solaris sogar einen speziellen Mechanismus dafür hat, der aufgerufen wird, wenn c99 wird anstelle von cc als Compiler verwendet .

Es wurde schließlich 2018 behoben. Das Update befindet sich in Version 2.28 der GNU C-Bibliothek. Die aktuelle „stabile“ Version von Debian, Version 9, ist Version 2.24 der GNU C-Bibliothek, und dieser Fehler manifestiert sich daher weiterhin, 14 Jahre nachdem er gemeldet wurde.

Wie in den Diskussionen zur GNU-C-Bibliothek erwähnt, gibt es die Möglichkeit von Software, die geschrieben wurde, um die Macken der GNU C-Bibliothek zu benötigen, ohne Rücksicht auf andere C-Bibliotheken wie Musl oder das Verhalten auf anderen Plattformen. In den vorgenannten Diskussionen über die Jahre wurde jedoch kein solches Programm identifiziert. Während mehrere Programme, die von der alten GNU-C-Bibliothek beschädigt wurden, Benutzer dazu auffordern, EOF zweimal hintereinander zu signalisieren, haben identifiziert worden; einschließlich unter anderem hexdump hier und patch auf StackOverflow im Jahr 2018.


Linux
  1. Warum druckt Man um 00:30 Uhr „Gimme Gimme Gimme“?

  2. Warum hat Ifs in `while Ifs=Read..` keine Auswirkung?

  3. Warum fügt die Ssh -t Option Cr &Lf in der umgeleiteten Ausgabe hinzu?

  4. Warum beginnt die Unix-Zeit am 1.1.1970?

  5. Warum wird select unter Linux verwendet

Warum jeder versuchen sollte, Linux zu verwenden

Warum funktioniert dieses „beim Lesen“ in einem Terminal, aber nicht in einem Shell-Skript?

Warum funktioniert `exit &` nicht?

Warum hat „/“ einen „..“-Eintrag?

Warum führt das Forking meines Prozesses dazu, dass die Datei unendlich gelesen wird?

Warum geht der Linux-Netzwerkverkehr nur über eth0?