向stdout写入struct后读取异常、输出随机值的原因排查
核心问题原因
代码打印随机值是两个叠加的逻辑错误导致的,和结构体本身的读写逻辑无关:
1. stdout 是单向只写流,不支持读取操作
stdout 是系统预定义的标准输出流,从stdio库的标记到系统文件描述符的访问权限,全程都是单向只写的,唯一用途是把程序内容输出到终端或重定向目标,根本没有提供读取能力:
- 哪怕你通过shell把stdout重定向到普通文件,stdio对stdout的只写标记依然不会改变,对它调用
fread时会直接因为权限校验失败,函数返回0,代表没有读取到任何有效字节 - 栈上声明的
struct Student steve没有做任何初始化,内存中是随机残留的垃圾值,printf打印的自然就是无意义的随机数
2. 缓冲机制会进一步阻断读写链路
就算强行让流支持读取,stdout默认的全缓冲模式也会让读写完全错位:
- 你通过
fwrite写入的john结构体数据,一开始是存在stdio库的用户态缓冲区中,没有同步到内核维护的流偏移位置 - 没有主动执行
fflush冲刷缓冲区的情况下,写操作的内容根本没有进入可读取的流位置,此时哪怕能发起读操作,也拿不到之前写入的数据
可复现正确读写逻辑的写法
要实现“写入结构体后再读回”的效果,不能直接操作单向的stdout,需要使用双向可读写的二进制文件流:
- 通过
fopen("temp.bin", "w+b")打开支持读写的二进制临时文件流 - 执行
fwrite写入结构体数据后,立刻调用fflush把缓冲区内容同步到内核 - 调用
rewind(fp)把流的读写指针重置到文件起始位置 - 再执行
fread读取刚才写入的内容,就能拿到正确的john结构体数据赋值给steve
内容的提问来源于stack exchange,提问作者user9679818
相关产品推荐
相关产品推荐

