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

Qt多QFile循环写入数据实现及QTextStream初始化崩溃问题排查

解决QTextStream操作QFile时的崩溃问题

你遇到的崩溃问题核心原因是局部QFile对象的生命周期问题,咱们一步步拆解清楚:

问题根源分析

  • 你在if(file_count == 1 && msg_line_count == -1)和else if(msg_line_count == 10)分支里创建的QFile file是栈上的局部变量,当代码执行完对应的分支块后,这个局部对象会被自动销毁,内存被系统回收。
  • 但你把current_record_file指向了这个栈对象的地址,后续再用这个指针操作QTextStream时,访问的已经是被释放的无效内存,属于野指针操作,必然导致程序崩溃。

修复后的代码实现

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) {
    ui->setupUi(this);
    simulateReceiveData();
}

MainWindow::~MainWindow() {
    // 析构时关闭并释放最后一个打开的文件,避免内存泄漏
    if (current_record_file) {
        QTextStream stream(current_record_file);
        stream << "END";
        stream.flush();
        current_record_file->close();
        delete current_record_file;
        current_record_file = nullptr;
    }
    delete ui;
}

void MainWindow::simulateReceiveData() {
    record_file_name_prefix = "D:/Project/MessageRecording";
    while(file_count <= 5){ // 调整条件,确保最多创建5个文件
        qDebug()<<"on recording ...";
        if(file_count == 1 && msg_line_count == -1){
            // 改用堆分配创建文件,延长对象生命周期
            QString record_file_name = record_file_name_prefix + "(1).asc";
            qDebug()<<"record_file_name is"<<record_file_name;
            current_record_file = new QFile(record_file_name);
            if (!current_record_file->open(QFile::WriteOnly | QFile::Truncate)){
                qDebug()<<QString("Fail to open file : %1").arg(record_file_name);
                delete current_record_file; // 打开失败要释放内存
                current_record_file = nullptr;
                return;
            }
            // 写入文件头
            QTextStream stream(current_record_file);
            stream << "START\r\n";
            msg_line_count = 0;
        }else if(msg_line_count == 10){
            // 关闭并释放前一个文件
            if (current_record_file) {
                QTextStream stream(current_record_file);
                stream << "END";
                stream.flush();
                current_record_file->close();
                delete current_record_file;
                current_record_file = nullptr;
            }
            // 创建下一个新文件
            file_count++;
            if (file_count >5) break; // 超过5个文件就停止循环
            QString record_file_name = record_file_name_prefix + QString("(%1).asc").arg(file_count);
            current_record_file = new QFile(record_file_name);
            if (!current_record_file->open(QFile::WriteOnly | QFile::Truncate)) {
                qDebug()<<QString("Fail to open file : %1").arg(record_file_name);
                delete current_record_file;
                current_record_file = nullptr;
                return;
            }
            // 写入新文件的文件头
            QTextStream stream(current_record_file);
            stream << "START\r\n";
            msg_line_count = 0;
        }else{
            // 写入主体内容前先检查指针有效性
            if (!current_record_file) break;
            QTextStream stream(current_record_file);
            stream <<"0.0000 0 Rx 00 00 00 00 00 00 00 00\r\n";
            msg_line_count++;
        }
        // 可选:加短延时,避免循环瞬间跑完,方便观察日志
        // QThread::msleep(100);
    }
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFile>
#include <QDateTime>
#include <QTextStream>
#include <QDebug>
#include <QThread> // 用于延时(可选)

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    void simulateReceiveData();
    int file_count = 1;//文件数量
    int msg_line_count = -1;//单个文件内的行数
    QString record_file_name_prefix;
    QFile* current_record_file = nullptr;//指向当前写入的文件
};

#endif // MAINWINDOW_H

关键修复点说明

  1. 改用堆分配QFile对象:用new QFile()创建文件对象,这样对象的生命周期由我们手动控制,不会在分支结束后被自动销毁。
  2. 添加内存释放逻辑:在析构函数、切换文件时,都要关闭旧文件并delete对应的QFile对象,避免内存泄漏。
  3. 增加指针有效性检查:在使用current_record_file前先判断是否为空,防止空指针访问。
  4. 调整循环条件:把while(file_count <5)改为while(file_count <=5),确保能创建最多5个文件,同时在切换文件时判断是否超过上限,及时退出循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 21:08:13