您的位置:首页 > 其它

一个让printf不正常工作的例子 - 已解决

2012-05-28 21:50 323 查看
话说今天做了一个课程实验,但是出了一点点问题,问题在于突然printf出现无法正常输出了..经过一翻小研究,发现了导致printf不正常的代码...但是不懂这段代码对应的那段软中断处理代码具体做了什么..所以没有继续研究下去..今天记录在此,希望在不久的将来能够查明是什么原因...


/* 一个让printf不正常工作的例子 */

/* 如果程序使用下面的一段汇编代码来实现返回操作系统,则printf向终端输出的字符流中,终端只显示字符流中最后一个\n符号前面的字符。
* 如果字符流没有\n,则所在字符都不能正常显示出来。
* 比如返回操作系统前,printf总共向终端输出如下字符流:
*
* XXXXXXXXXXX\n
* Xxxxxxxxxxxxxxxx\n\xxxxxx
* xxxxxxxxxxxxxx\n
* YYYYYYYYYYYYYYYyyyyyy
*
* 这样最后一符的所有Y都不会显示出来,事实上是最后一个\n后面的所有字符都不会在终端前面显示出来。
*
* 测试环境
* gcc版本:
*	gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
* ubuntu版本:
* 	Linux abee-lisa-linux 2.6.35-32-generic #64-Ubuntu SMP Mon Jan 2 23:31:33 UTC 2012 i686 GNU/Linux
*
* 目前暂不知道到底这个软中断具体做了什么,so..留着有待研究咯.
*/

/* 哪个大哥大姐知道这是怎么回事的,望指点指点迷津呀。 ^_^ */

#include <stdio.h>

int main()
{
printf("this is a string with \\n \n");
printf("this is a string with \\n \n");

printf("this is a string without \\n");
/* 直接内联汇编 */
__asm__("movl $1,%eax\n \
movl $0,%ebx\n \
int $0x80");		//是返回操作系统了,并以返回值0返回。但是却影响了终端的显示。

//exit(0);		/* 真正的exit(0); */
return 0;
}

/* 正常的输出应该是:
* this is a string with \n
* this is a string with \n
* this is a string without \n
* 但是,如果采用不同的返回操作系统的方式,結果是不一样的。
*/


[/code]
原因解释(2014-11-01):

这里有个背景:针对终端设置,printf输出缓冲模式是行模式,即遇到\n就会真正flush到终端上,否则先缓存,直到缓冲区满了才flush到终端上。

这里内联汇编中的代码实现的是返回操作系统,注意这里是直接由汇编代码返回,因此隐藏了一个程序在正常返回操作系统之前所隐藏的逻辑,如关闭文件、清空缓存区等等。

这里最后一个\n后面的没有输出的原因就是少了正常退出所做的清空缓存逻辑,这段代码和_exit(0)功能一样(注意是_exit(),需包含unistd.h)。


对于exit(0)和return 0;这两个方式其实都含有清空缓存区的逻辑,因此在返回操作系统前会正常见到预期输出的数据。


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐