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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:27:34