Windows下创建QList<QLine>触发崩溃的技术求助
Windows平台QList在drawBackground中崩溃的排查与解决
问题现象
在Windows平台编译运行Qt程序时,在QGraphicsScene::drawBackground函数中创建QList<QLine>对象并调用append方法会触发异常,崩溃发生在QArrayDataPointer<QLine>的析构阶段。
崩溃调用栈信息:
> basic_example.exe!QArrayDataPointer<QLine>::~QArrayDataPointer<QLine>() Line 112 C++ basic_example.exe!QArrayDataPointer<QLine>::reallocateAndGrow(QArrayData::GrowthPosition where, __int64 n, QArrayDataPointer<QLine> * old) Line 250 C++ basic_example.exe!QArrayDataPointer<QLine>::detachAndGrow(QArrayData::GrowthPosition where, __int64 n, const QLine * * data, QArrayDataPointer<QLine> *old) Line 210 C++ basic_example.exe!QtPrivate::QPodArrayOps<QLine>::emplace<QLine const &>(__int64 i, const QLine & <args_0>) Line 179 C++ basic_example.exe!QList<QLine>::emplaceBack<QLine const &>(const QLine & <args_0>) Line 886 C++ basic_example.exe!QList<QLine>::append(const QLine & t) Line 459 C++
相关调试截图:

可复现最小示例代码
#include <cstdlib> #include <QtWidgets/qapplication.h> #include<QtWidgets/qgraphicsview.h> #include<QtWidgets/qwidget.h> #include<QtWidgets/qboxlayout.h> #include <QtWidgets/qgraphicsscene.h> #include <QtGui/qpainter.h> class GraphicsScene : public QGraphicsScene { public: GraphicsScene (QGraphicsScene* parent = nullptr) : QGraphicsScene (parent) { int scene_width = 64000; int scene_height = 64000; // Set the focus to be in the middle of the view when it's created. setSceneRect (-scene_width / 2, -scene_width / 2, scene_width, scene_height); }; private: void drawBackground (QPainter* painter, const QRectF& rect) { QGraphicsScene::drawBackground (painter, rect); QList<QLine> lines; QLine line_that_crashes = QLine (0, 0, 100, 100); lines.append (line_that_crashes); } }; class Window : public QWidget { public: Window (QWidget* parent = nullptr) : QWidget (parent) { setGeometry (200, 200, 1024, 768); setWindowTitle ("Minimum Window"); layout_ = new QVBoxLayout (); layout_->setContentsMargins (0, 0, 0, 0); setLayout (layout_); graphics_scene_ = new GraphicsScene (); view_ = new QGraphicsView (this); view_->setScene (graphics_scene_); layout_->addWidget (view_); show (); } private: QGraphicsScene* graphics_scene_; QBoxLayout* layout_; QGraphicsView* view_; }; int main (int argc, char *argv[]) { QApplication application(argc, argv); Window wnd; return application.exec(); }
崩溃原因分析
- 编译选项不匹配:这是最常见的诱因。如果Qt库与应用程序的编译选项不一致(如Qt用动态CRT(
MD)编译,应用程序用静态CRT(MT);或Debug/Release模式混合使用),会导致内存分配器不兼容,QList在堆内存分配/释放时触发错误。 - Qt版本bug:部分旧版本Qt在处理
QLine这类被识别为POD类型的对象时,QList的内部内存管理逻辑存在缺陷,导致析构阶段触发异常。 - 堆内存损坏:程序其他部分存在越界访问、野指针等问题时,会破坏堆结构,恰好在此处触发崩溃。
解决方法
- 统一编译选项:确保应用程序的编译选项(CRT模式、Debug/Release、32/64位)与所使用的Qt库完全一致。例如Qt库是Debug+MD,应用程序也必须设置为相同配置。
- 替换QList为QVector:
QVector的内存实现更直接稳定,对POD类型的处理没有QList的小对象优化逻辑,可避开相关bug,将代码中的QList<QLine>替换为QVector<QLine>即可。 - 升级Qt版本:若使用较旧的Qt版本(如Qt5.12之前),升级到最新稳定版(如Qt5.15 LTS或Qt6.x),修复已知的内存管理bug。
- 排查堆损坏问题:使用内存检测工具(如Visual Studio的AddressSanitizer、Qt Creator的Valgrind)检查程序中是否存在越界访问、野指针等导致堆损坏的代码。
内容的提问来源于stack exchange,提问作者Swatcat
相关产品推荐
相关产品推荐

