簡體   English   中英

標准輸出重定向更改 output

[英]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,並且隨着代碼的其他部分對堆棧和/或堆。

我會仔細檢查您的代碼是否存在問題,例如緩沖區溢出、返回指向堆棧上變量的指針的函數等。

使用調試器單步執行代碼可能會很有成效(或者如果您不走運,它可能會再次改變行為。)。

您已經看到了一些有趣的事情:

  1. stdout的重定向如何可能影響任何事情? 可能是因為它導致 C 庫的行為有點不同:stream 使用不同的緩沖模式,具體取決於它是否連接到終端設備(參見GNU libc 文檔C99 §7.9.13 段。 7)。

  2. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM