结构体含指针时不能直接fwrite,否则只写指针值而非所指数据;必须手动序列化元信息(如长度)和实际内容,处理空指针、字节序、二进制模式等细节。

结构体含 char* 或 int* 时不能直接 fwrite
直接对结构体变量调用 fwrite 会把指针值(比如 0x7fff12345678)写进文件,而不是它指向的数据。读取时再 fread 出来的只是个无效地址,解引用必崩。
常见错误现象:Segmentation fault、读出乱码、内容长度对不上。
- 必须区分“结构体本身”和“结构体持有的堆内存”两部分数据
- 序列化顺序要和反序列化严格一致:先写元信息(如字符串长度),再写实际内容
- 如果结构体嵌套多层指针,每层都要手动处理,不能依赖 memcpy
std::vector 和 std::string 能直接 fwrite 吗?
不能。虽然它们内部是连续内存,但对象本身包含控制字段(如 size、capacity、指针),fwrite(&vec, sizeof(vec), 1, fp) 写的是这些字段的二进制位,不是数据内容。
使用场景:想存 std::vector<int> nums = {1,2,3}</int>,目标是文件里连续四个 int(长度 + 三个元素)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 正确做法:先写
nums.size(),再写nums.data()指向的内存 - 注意
std::string同理,得先写str.length(),再写str.c_str() - 跨平台时小心字节序——如果文件要在不同 CPU 架构间交换,需统一用
htonl等转换
手动序列化时如何处理空指针和边界
写入前不检查 ptr == nullptr,会导致 fwrite(nullptr, ...) 崩溃;读取时不验证长度,可能越界读或内存泄漏。
参数差异:写入长度字段用 uint32_t 比 size_t 更安全,避免 32/64 位平台不一致。
- 写入前:用
if (p != nullptr) { fwrite(p, 1, len, fp); },同时写一个标志位或长度(0 表示空) - 读取时:先读长度
uint32_t len,若为 0 则分配nullptr,否则malloc(len)+fread - 记得用
ferror(fp)检查每次 IO 是否成功,别只信fwrite返回值
用 std::ofstream 的 write 还是 C 风格 fwrite?
没本质区别,都是裸写内存。C++ 流默认带缓冲,但二进制序列化通常关掉:用 file.rdbuf()->pubsetbuf(nullptr, 0) 或直接用 FILE* 更可控。
性能影响:频繁小块写入时,自己做缓冲比每字段都 write 快;兼容性上 fwrite 在嵌入式或旧系统更稳。
- 推荐统一用
FILE*+fwrite/fread,避免流状态干扰(比如意外触发格式化) - 打开文件务必用
"wb"/"rb",Windows 下缺b会把\n换成\r\n - 结构体里有虚函数或继承关系?直接序列化会出错——这类对象必须用自定义序列化逻辑,不能按内存布局硬拷
b 标志。这四点踩中任一个,文件就只能本机读一次。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










