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
关键修复点说明
- 改用堆分配QFile对象:用
new QFile()创建文件对象,这样对象的生命周期由我们手动控制,不会在分支结束后被自动销毁。 - 添加内存释放逻辑:在析构函数、切换文件时,都要关闭旧文件并
delete对应的QFile对象,避免内存泄漏。 - 增加指针有效性检查:在使用
current_record_file前先判断是否为空,防止空指针访问。 - 调整循环条件:把
while(file_count <5)改为while(file_count <=5),确保能创建最多5个文件,同时在切换文件时判断是否超过上限,及时退出循环。
内容的提问来源于stack exchange,提问作者iwtbae
相关产品推荐
相关产品推荐

