Terima kasih kepada @JdeBP atas petunjuknya, saya dapat membuat testcase kecil yang berfungsi sama dengan 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;
}
}
Saat dijalankan pada sistem berbasis glibc (desktop linux tipikal).
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
Saat dijalankan di bsd, solaris, busybox (uclibc), android, dll:
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
Berdasarkan interpretasi standar saya yang tidak ahli, ini terlihat seperti bug di glibc (library GNU C).
Tentang fread
:
Untuk setiap objek, pemanggilan ukuran harus dilakukan ke fungsi fgetc() dan hasilnya disimpan, dalam urutan dibaca, dalam larik karakter tak bertanda yang persis menutupi objek.
Tentang fgetc
:
Jika indikator akhir file untuk aliran input yang diarahkan ke bystream tidak disetel dan byte berikutnya hadir, fungsi fgetc() akan mendapatkan byte berikutnya
Tampaknya glibc akan mencoba "mendapatkan byte berikutnya" meskipun indikator eof disetel.
Memang, itu sebenarnya bug di pustaka GNU C, tidak ada di pustaka BSD atau musl C. Itu diketahui pada tahun 2005. Ulrich Drepper menutup laporan bug tanpa memperbaiki bug pada tahun 2007. Itu telah dibahas pada tahun 2012, di mana dicatat bahwa perpustakaan C lain tidak dan tidak memiliki perilaku ini, bahwa Standar C 1999 cukup spesifik tentang itu, dan bahwa Solaris bahkan memiliki mekanisme khusus untuk ini yang dipanggil saat c99
digunakan sebagai kompiler alih-alih cc
.
Itu akhirnya diperbaiki pada tahun 2018. Perbaikannya ada di versi 2.28 dari pustaka GNU C. Versi Debian yang "stabil" saat ini, versi 9, berada pada versi 2.24 pustaka GNU C, dan bug ini terus muncul dengan sendirinya, 14 tahun setelah dilaporkan.
Seperti disebutkan dalam diskusi pustaka GNU C, ada kemungkinan perangkat lunak yang ditulis untuk memerlukan keanehan perpustakaan GNU C tanpa memperhatikan perpustakaan C lainnya seperti musl atau perilaku pada platform lain. Namun, dalam diskusi tersebut selama bertahun-tahun tidak ada program seperti itu yang teridentifikasi. Sedangkan beberapa program yang dirusak oleh pustaka GNU C lama, untuk mengharuskan pengguna memberi sinyal EOF dua kali berturut-turut, telah telah diidentifikasi; termasuk antara lain hexdump
di sini dan patch
di StackOverflow pada tahun 2018.