[英]stdout redirect changing output
我有一個名為abc
的程序。
當我運行以下命令時:
$ ./abc < infile
我得到以下 output:
ijklm
但是,當我運行時:
$ ./abc < infile > outfile
$ cat outfile
我得到了這個 output:
ijkoo
現在,我假設這是我的程序的一個錯誤。 但是,無論我的程序在做什么,我都不知道這怎么可能。
編輯:
現在我知道這是可能的,我很好奇我的程序中是什么導致了這種情況。
我的程序中的循環中有一個塊,其中包含:
byte = ascii_to_byte(asciibyte);
putchar(byte);
byte 是char
類型。
現在,如果我將putchar(byte)
更改為printf("%c", byte)
所有 output 保持不變。
但是,如果我將其更改為printf("%d", byte)
,則$./abc < infile
輸出:
105106107111111
這是那些 ascii 字符在outfile
中的十進制表示。 但這不是字符的十進制表示,因為它們剛剛被發送到標准輸出時實際出現。 我不明白為什么會有這種差異。
編輯#2:
如果我將打印行更改為printf("%c\n", byte)
,則$./abc < infile
輸出:
i
j
k
o
o
這與 outfile 中的內容一致。 同樣,不確定有什么區別。
編輯#3
我剛剛在 32 位機器上測試了這個,程序可以工作: outputfile
包含ijklm
。 奇怪。
編輯#4
這里主要是function:
int main()
{
char asciibyte[8];
char byte;
int c; //Using int to avoid the EOF pitfall.
long charcount = 0;
while((c = getchar()) != EOF){
if(c != '0' && c != '1'){
continue;
}
asciibyte[charcount % 8] = c;
if(charcount % 8 == 7){
/*Testing revealed that at this point asciibyte does contain
what it should contain, eight ASCII ones and zeros representing
a byte read in from stdin*/
byte = ascii_to_byte(asciibyte);
/*Print statements such as:
printf("%d", byte);
printf("%c\n", byte);
reveal that the ascii_to_byte function works incorrectly on my
64 bit machine. However these statements:
putchar(byte);
printf("%c", byte);
make it appear as though the function operates as it should.
EXCEPT if i redirect that output to a file.*/
putchar(byte);
}
charcount++;
}
return 0;
}
這是 ascii_to_byte function:
char ascii_to_byte(char *asciibyte){
char byte;
int i;
for(i = 0; i < 8; ++i){
if(asciibyte[7-i] == '1'){
byte = byte | (1 << i);
}
}
return byte;
}
最終編輯
我注意到我應該將字節初始化為 0x00。 問題解決了。 為什么我會這么遲鈍? 我會給任何可以具體解釋這如何導致問題的人提供答案。
這種奇怪的行為,根據看似無關的變化來來去去,可能表明您的程序不應該讀取或寫入 memory,並且隨着代碼的其他部分對堆棧和/或堆。
我會仔細檢查您的代碼是否存在問題,例如緩沖區溢出、返回指向堆棧上變量的指針的函數等。
使用調試器單步執行代碼可能會很有成效(或者如果您不走運,它可能會再次改變行為。)。
您已經看到了一些有趣的事情:
stdout
的重定向如何可能影響任何事情? 可能是因為它導致 C 庫的行為有點不同:stream 使用不同的緩沖模式,具體取決於它是否連接到終端設備(參見GNU libc 文檔或C99 §7.9.13 段。 7)。
當printf("%d", byte)
和printf("%c\n", byte)
都改變行為時,為什么將putchar(byte)
更改為printf("%c", byte)
不會改變任何東西? 也許是因為編譯器會自動將printf("%c", byte)
重寫為更有效的putchar(byte)
- 模糊的 GCC 的最新版本通常會這樣做,即使沒有啟用優化 - 而printf("%d", byte)
並且printf("%c\n", byte)
確實將被編譯為對printf()
的調用。
這當然是可能的 - 程序可以檢查它是否正在寫入終端並寫入與寫入 pipe 時寫入的內容不同的內容。
正如你所說, byte
未初始化,所以任何事情都可能發生。
可能發生的事情之一是, byte
“開始”在 0 並保持其值從 function 調用到 function 調用(就好像它被聲明為static
)。
in binary ... byte | c (bin) | byte | c -----------+--------------+-------------- 00000000 | i (01101001) | 01101001 (i) 01101001 | j (01101010) | 01101011 (k) * strange you get 'j', but anything can happen :) 01101011 | k (01101011) | 01101011 (k) 01101011 | l (01101100) | 01101111 (o) 01101111 | m (01101101) | 01101111 (o)
尼爾·巴特沃斯所說的。 function 稱為isatty
。
if (isatty(STDOUT)) printf("I am printing to the terminal!\n");
此外,在測試東西時,您可能已經做過:
$ ./abc < infile > infile
意外地。 因此,您可能想快速檢查一下,該infile
是否確實包含相同的數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.