缓冲输出和内存分配

来源:互联网 发布:如何开展网络推广工作 编辑:程序博客网 时间:2024/05/21 08:04
 
 程序输出有两种方式:一种是即时处理方式,另一种是先暂存起来,然后再大块写入的方式,前者往往造成较高的系统负担。因此,C语言实现通常都允许程序员进行实际的写操作之前控制产生的输出数据量。
   这种控制能力一般是通过库函数setbuf实现的。如果buf是一个大小适当的字符数组,那么
   setbuf(stdout,buf);
   语句将通知输入/输出库,所有写入到stdout的输出都应该使用buf作为输出缓冲区,知道buf缓冲区被填满或者程序员直接调用fflush(注:对于由写操作打开的文件,调用fflush将导致输出缓冲区的内容被实际的写入该文件),buf缓冲区中的内容才实际写入到stdout中。缓冲区的大小由系统头文件<stdio.h>中的BUFSIZ定义。
  下面的程序的作用是把标准输入的内容复制到标准输出中,演示了setbuf库函数最显而易见的用法:
#include <stdio.h>
 
main()
{
    int c;
    char buf[BUFSIZ];
    setbuf(stdout,buf);
 
     while((c=getchar())!= EOF)
        putchar(c);
}
 
   遗憾的是,这个程序是错误的,仅仅是因为一个细微的原因。程序中对库函数setbuf的调用,通知了输入/输出库所有字符的标准输出应该首先缓存在buf中。要找到问题出自何处,我们不妨思考一下buf缓冲区最后一次被清空是在什么时候?答案是在main函数结束之后,作为程序交回控制给操作系统之前C运行时库所必须进行的清理工作的一部分。但是,在此之前buf字符数组已经被释放!
   要避免这种类型的错误的办法是:让缓冲数组成为静态数组,既可以直接显式声明buf为静态:
    staticchar buf[BUFSIZ];
也可以把buf声明完全移到main函数之外。
第二种方法是动态分配缓冲区,在程序中并不主动释放该缓冲区,这样c运行是库进行清理工作时就不会发生缓冲区已经被释放的情况
char *malloc();
setbuf(stdout,malloc(BUFSIZE));
这里其实并不需要检查malloc函数调用是否成功,如果malloc函数调用失败将会返回一个null指针,setbuf函数的第二个参数可以为null,此时标准库不需要进行缓冲。这种情况下程序仍然能够工作,只不过速度慢一些而已
0 0
原创粉丝点击