C stdout重定向更改输出
我有一个叫做abc的程序 当我运行以下命令时:C stdout重定向更改输出,c,unix,C,Unix,我有一个叫做abc的程序 当我运行以下命令时: $ ./abc < infile 但是,当我跑步时: $ ./abc < infile > outfile $ cat outfile 现在,我假设这是我的程序的一个bug。然而,不管我的程序在做什么,我不知道这是怎么可能的 编辑: 现在我知道这是可能的,我很好奇我的程序中是什么导致了这一点 在我的程序中,循环中有一个块包含: byte = ascii_to_byte(asciibyte); putchar(byte); 字
$ ./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
containsijklm
。维尔德
编辑#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
的输出是什么你需要开始缩小问题的范围。理想情况下,你希望看到一页仍然存在问题的代码,可以发布在这里。在整理内容并用实体模型替换时,要仔细观察任何可能产生副作用或可能溢出缓冲区的内容。