首页
社区
课程
招聘
[原创]C语言的文件与缓冲区
发表于: 2024-9-1 21:31 4829

[原创]C语言的文件与缓冲区

2024-9-1 21:31
4829

在C语言中,有三个预定义的文件流:stdin,stdout,stderr,在VC++6的stdio.h中,它们的定义如下:

分别取自_iob数组下标为0、1、2的元素地址。

_iob的定义是一个FILE类型的数组:

FILE本质上是结构体_iobuf的类型别名:

结构体_iobuf中的_ptr,_base,_cnt,_bufsiz是与文件缓冲区相关的字段。

在使用fopen函数打开一个文件后,就会从_iob数组中选择一个空闲的元素分配给新的FILE。


先准备一段C代码


将断点打在fopen处:

逐层步入:


一直到这里调用了系统函数CreateFile:


待fopen返回之后,fp便分配了值,而该值恰好是_iob数组下标为3的元素地址,0、1、2已经被预先占用了,所以新打开的文件从3开始。


在监视窗口中展开fp的内容可见,缓冲区相关的字段都为0,说明文件刚打开时,缓冲区尚未分配。

_flag = 0x80,转换为二进制是10000000,其中一个bit位置1,表示_iob数组中该元素已被占用。

_file = 3,代表文件标识,也是它在_iob数组中的下标。


文件缓冲区只有在文件真正被读写时才会分配,比如执行完fprintf后:

_base = 0x00382a80,代表文件缓冲区的起始地址;

_ptr是文件指针,指示当前写入到缓冲区的哪个位置;

_bufsiz = 0x1000,说明缓冲区大小是4096字节;

_cnt = 0x0fb1,说明缓冲区还剩余4017字节,也就是说刚刚写入了4096-4017=79字节数据;

_flag=0x8a,二进制为10001010,新增了两个置1的bit位。


在内存视图中,跳转到_base指向的内存区域,发现下面有大量0xCDCD填充的字节,很明显这是一块堆内存(可以参考我的另一篇文章:[原创]VC++6调试状态下的堆结构),堆块起始地址在向前偏移32字节处也就是0x00382a60,根据堆块的附加信息可知:blockType = 2也就是_CRT_BLOCK,是C运行时库所使用的类型。


注意,此时仅仅是将数据写入了内存缓冲区,实际磁盘文件中并没有内容:


如果想要将缓冲区的内容写入到磁盘,可以等待缓冲区满后自动触发存盘,也可以手动调用fflush手动同步,步入到fflush函数内部:


这里调用了WriteFile系统函数:

WriteFile执行后,磁盘中的文件便有了内容:


fflush函数返回后,缓冲区相关字段也发生了变化:


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//