You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

二进制读取Dog类时程序崩溃,写入代码正常求解决

问题分析与解决方案

嘿,我来帮你搞定这个崩溃问题!你的写入代码运行正常,但读取逻辑里有两个关键错误导致了程序崩溃,咱们一个个来看:

1. 未初始化的野指针导致内存访问错误

在读取代码里,你只声明了Dog* dog;,但这个指针并没有指向任何有效的内存空间——它的值是随机的垃圾地址。当你调用fread(dog, sizeof(Dog), 1, file);时,程序会尝试把文件数据写入这个随机地址,直接触发内存访问违规,这就是崩溃的直接原因。

修复方法:

你需要给指针分配有效的内存,或者直接使用栈上的对象:

方式一:使用栈对象+拷贝到堆(推荐,更安全)

FILE* file = fopen(filePath.toStdString().c_str(), "rb");
if (file == NULL) {
    QMessageBox::critical(this, "Ошибка!", "Ошибка при открытии файла!");
    return;
}

Dog tempDog; // 栈上分配对象,自动管理内存
while (fread(&tempDog, sizeof(Dog), 1, file) == 1) {
    _list->emplace_back(new Dog(tempDog)); // 拷贝到堆内存,加入列表
}
fclose(file);

方式二:直接在堆上分配内存

FILE* file = fopen(filePath.toStdString().c_str(), "rb");
if (file == NULL) {
    QMessageBox::critical(this, "Ошибка!", "Ошибка при открытии файла!");
    return;
}

Dog* dog;
while (true) {
    dog = new Dog(); // 分配堆内存
    if (fread(dog, sizeof(Dog), 1, file) != 1) {
        delete dog; // 读取失败时释放内存,避免泄漏
        break;
    }
    _list->emplace_back(dog);
}
fclose(file);

2. while (!feof(file))的错误用法

feof()函数只有在尝试读取超出文件末尾之后才会返回true,所以你的原循环会多执行一次:当最后一次fread已经读取失败时,你仍然会把无效的dog指针加入列表,这也可能导致后续的崩溃或异常行为。

正确的做法是直接判断fread的返回值——fread会返回成功读取的元素个数,当返回值不等于1时,说明已经读到文件末尾或者读取失败,此时应该退出循环。

额外注意事项

如果你的Dog类包含非POD类型的成员(比如std::string、QString、动态分配的数组等),直接用fread/fwrite二进制读写会导致问题:这些成员存储的是内存指针,写入文件后,再读取时指针指向的地址已经无效,会引发未定义行为。

这种情况下,建议使用Qt的序列化机制(比如QDataStream)来处理对象的读写,它能正确处理Qt类型和自定义类型的序列化。

内容的提问来源于stack exchange,提问作者garbart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:09:13