C stdout重定向更改输出

C stdout重定向更改输出,c,unix,C,Unix,我有一个叫做abc的程序 当我运行以下命令时: $ ./abc < infile 但是,当我跑步时: $ ./abc < infile > outfile $ cat outfile 现在,我假设这是我的程序的一个bug。然而,不管我的程序在做什么,我不知道这是怎么可能的 编辑: 现在我知道这是可能的,我很好奇我的程序中是什么导致了这一点 在我的程序中,循环中有一个块包含: byte = ascii_to_byte(asciibyte); putchar(byte); 字

我有一个叫做abc的程序

当我运行以下命令时:

$ ./abc < infile
但是,当我跑步时:

$ ./abc < infile > outfile
$ cat outfile
现在,我假设这是我的程序的一个bug。然而,不管我的程序在做什么,我不知道这是怎么可能的

编辑:

现在我知道这是可能的,我很好奇我的程序中是什么导致了这一点

在我的程序中,循环中有一个块包含:

byte = ascii_to_byte(asciibyte);
putchar(byte);
字节的类型为
char

现在,如果我将
putchar(byte)
更改为
printf(“%c”,byte)
所有输出保持不变

但是,如果我将其更改为
printf(“%d”,byte)
,则
$./abc
输出:

105106107111111
i
j
k
o
o
这是那些ascii字符的十进制表示形式,就像它们在
outfile
中一样。但它不是字符的十进制表示形式,因为它们在刚被发送到stdout时实际出现。我不明白为什么会有这种差异

编辑#2:

如果我将打印行更改为
printf(“%c\n”,byte)
,则
$./abc
输出:

105106107111111
i
j
k
o
o
这与输出文件中的内容一致。再说一次,我不知道有什么区别

编辑#3

我刚刚在一台32位机器上测试了这个程序,程序运行正常:
outputfile
contains
ijklm
。维尔德

编辑#4

以下是主要功能:

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;
}
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;
}
下面是ascii_to_字节函数:

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;
}
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;
}
char ascii字节到字节(char*asciibyte){
字符字节;
int i;
对于(i=0;i<8;++i){
if(ascibyte[7-i]=“1”){

byte=byte |(1这当然是可能的-程序可以检查它是否正在写入终端,并写入与写入管道时不同的内容。

正如尼尔·巴特沃斯所说。该函数被调用

此外,在测试内容时,您可能已经完成了以下工作:

$ ./abc < infile > infile
$。/abcinfle

偶然。因此,您可能希望快速检查
infle
是否确实包含相同的数据。

这种奇怪的行为,根据看似不相关的更改来来去去去,可能表明您的程序从内存中读取或写入了它不应该读取的内容,并且该行为会随着代码的其他部分而改变对堆栈和/或堆进行不同的使用

我会仔细检查你的代码是否有不好的地方,比如缓冲区溢出、返回堆栈上变量指针的函数等等

使用调试器单步执行代码可能会很有成效(如果您运气不好,它可能会再次改变行为!)

你已经看到了一些有趣的事情:

  • stdout
    的重定向如何可能影响任何事情?可能是因为它导致C库的行为有点不同:流使用不同的缓冲模式,这取决于它是否连接到终端设备(请参阅或§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()
    的调用


  • 正如您所说,
    byte
    未初始化,因此任何事情都可能发生

    可能发生的事情之一是,
    byte
    从0开始,并在函数调用到函数调用之间保持其值(就好像它被声明为
    static

    在二进制中。。。 字节| c(bin)|字节| c -----------+--------------+-------------- 00000000 | i(011001)| 011001(i) 01101001 | j(011010)124101011(k)*奇怪的是,你会得到“j”,但任何事情都可能发生:) 011011 | k(011011)| 011011011(k) 011011 | l(01101100)| 0110111(o) 01101111 | m(01101101)| 01101111(o)
    是的,我已经用不同的测试输入做了很多次了,但我仍然没有。输出总是一样的吗?如果你运行了几次/abc,你会得到相同的结果吗?是的,输出在多次试验中是一致的。在这一点上,
    /abc
    的输出是什么你需要开始缩小问题的范围。理想情况下,你希望看到一页仍然存在问题的代码,可以发布在这里。在整理内容并用实体模型替换时,要仔细观察任何可能产生副作用或可能溢出缓冲区的内容。