-
-
[原创]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函数返回后,缓冲区相关字段也发生了变化:
赞赏
- [原创]从底层视角看面向对象 6346
- [原创]C语言的文件与缓冲区 4830
- [原创]CC1利用链分析 5096
- [原创]VC++6调试状态下的堆结构 4685
- [原创]URLDNS反序列化利用链 5845