会,且大概率段错误或未定义行为;因fwrite和write()不校验指针合法性,仅按所给地址与长度硬拷贝,若传入nullptr、已释放内存、未初始化指针或局部数组地址(函数返回后失效),则立即崩溃或数据错乱。

直接用指针写入文件缓冲区会崩溃吗?
会,而且大概率是段错误(Segmentation fault)或未定义行为。C++ 标准库的 std::ofstream 或 C 的 fwrite 不接受裸指针作为“缓冲区起点”并自动管理内存——它只信任你传入的地址确实可读、长度合法、且生命周期覆盖整个写入过程。如果你传的是栈上临时数组地址、已释放的堆内存、或未初始化的指针,程序立刻不可靠。
fwrite 要求指针指向有效内存,不是“能用就行”
fwrite 本身不校验指针合法性,它只按你给的地址和字节数硬拷贝。常见踩坑点:
- 传了
nullptr或未初始化指针 → 崩溃 - 传了局部数组但函数已返回 → 地址可能被复用,数据错乱
- 用
new分配但没检查是否成功 →fwrite对nullptr无防护 - 计算字节数时用了
sizeof(ptr)而非sizeof(*ptr) * count→ 只写 4 或 8 字节(指针大小),而非实际数据
正确示例:
int* data = new int[100];
// ... 填充 data ...
FILE* fp = fopen("out.bin", "wb");
if (fp && data) {
size_t written = fwrite(data, sizeof(int), 100, fp); // 注意:第二个参数是单元素大小
fclose(fp);
}
delete[] data;
std::ofstream 和 write() 怎么安全传指针?
std::ofstream::write() 接收 const char* 和 std::streamsize,所以你要把任意类型指针转成 const char*,且确保目标内存连续、未析构:
- 不能直接传
int*→ 编译失败,必须reinterpret_cast<const char>(ptr)</const> - 字节数必须显式算:比如写 100 个
int,要传100 * sizeof(int),不是100 - 如果对象含虚函数、非平凡构造/析构(如
std::string),reinterpret_cast写二进制是错的——只能用于 POD 类型
安全写法:
struct Record { int id; double value; }; // POD
Record* buf = new Record[50];
// ... 初始化 ...
std::ofstream f("data.bin", std::ios::binary);
if (f.is_open()) {
f.write(reinterpret_cast<const char>(buf), 50 * sizeof(Record));
}
delete[] buf;</const>
缓冲区生命周期比文件操作更关键
文件写入慢,系统可能延迟刷盘,但指针所指内存一旦释放,哪怕写操作还没真正落盘,fwrite 或 write() 已经读完了那片内存——后续行为完全不可控。最容易被忽略的是:
- 用
std::vector的.data()传指针 → 必须保证 vector 在整个写入期间不 resize、不析构 - 用 lambda 捕获局部变量指针 → 出作用域后指针失效,哪怕异步写也不行
- 多线程写同一文件 →
fwrite不是线程安全的,需加锁;std::ofstream同样不保证并发安全
真正可控的做法:写之前 memcpy 到独立缓冲区,或用 RAII 管理内存生命周期(如 std::unique_ptr<uint8_t></uint8_t> 配合 std::move 语义传递所有权)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











