簡體   English   中英

Qt 4.8 endInsert/RemoveRows 導致內存泄漏?

[英]Qt 4.8 endInsert/RemoveRows cause memory leak?

在此處輸入圖片說明 最近我對我的 Qt 4.8 應用程序進行了一些壓力測試。 我已經看到使用 valgrind massif 工具,它會導致堆內存擴展......

使用該工具,我發現此內存是通過此堆棧跟蹤分配的(這是另一個 massif 調用,因此值與屏幕截圖中的值不同):

->02.11% (1,133,952B) 0x221FD9EB: ??? (in /usr/lib/x86_64-linux-gnu/qt4/plugins/accessible/libqtaccessiblewidgets.so)
| ->02.11% (1,133,952B) 0x80ADE69: QAccessible::queryAccessibleInterface(QObject*) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.7)
|   ->01.18% (637,824B) 0x80B5156: ??? (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.7)
|   | ->01.18% (637,824B) 0x8BA0F6E: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.7)
|   |   ->01.18% (637,824B) 0x8BF1472: QAbstractItemModel::rowsInserted(QModelIndex const&, int, int) (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.7)
|   |     ->01.18% (637,824B) 0x8B86510: QAbstractItemModel::endInsertRows() (in /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.7)
|   |       ->01.18% (637,824B) in 5 places, all below massif's threshold (1.00%)

擴展的原因是 endInsertRows 和 endRemoveRows 函數。 我的 ModelView 實現如下所示:

void TrainScheduleModelView::addTrain(const model::object::Train &train)
{
    if (this->m_rows == TrainScheduleModelView::MAX_TRAIN_SCHEDULE_SIZE)
    {
        beginRemoveRows(QModelIndex(),
                        TrainScheduleModelView::MAX_TRAIN_SCHEDULE_SIZE - 1,
                        TrainScheduleModelView::MAX_TRAIN_SCHEDULE_SIZE - 1);
        endRemoveRows();
    }

    beginInsertRows(QModelIndex(), 0, 0);
    this->m_trains[this->m_head].second = train;
    this->m_trains[this->m_head].first = true;

    if (0 == this->m_head)
    {
        this->m_head = TrainScheduleModelView::MAX_TRAIN_SCHEDULE_SIZE - 1;
    }
    else
    {
        --(this->m_head);
    }

    if (this->m_rows < TrainScheduleModelView::MAX_TRAIN_SCHEDULE_SIZE)
    {
        ++(this->m_rows);
    }
    endInsertRows();
}

該模型特意基於 C 數組,每次添加新對象時,都會截斷最后一個。

誰能告訴我是否存在錯誤,或者我使用錯誤?

我有兩次嘗試解決它:

  1. 首先,我試圖消除可訪問性模塊 - 我希望沒有必要。 我必須使用./configure ... -no-accessibility...選項從源代碼構建 Qt。 案件已解決,但應用程序的 UI 受到了極大的影響。 我無法輸入密碼,因為鍵盤被阻止了。 所以這個解決方案是不可接受的。
  2. 下一個解決方法是消除動態行插入。 我改變了方法,而不是模擬行插入,我總是返回固定數量的行(顯示空行,但里面沒有數據)。 當我在表中放入一些數據時,我會發出dataChanged信號,所有行都受到影響(因為每一行都被移動了)。 該解決方案消除了使用 queryAccessibleInterface 功能,並且沒有泄漏。 所以代碼看起來是這樣的:
void TrainScheduleModelView::addTrain(const model::object::Train &train)
{
    this->m_trains[this->m_head].second = train;
    this->m_trains[this->m_head].first = true;

    if (0 == this->m_head)
    {
        this->m_head = TrainScheduleModelView::MAX_TRAIN_SCHEDULE_SIZE - 1;
    }
    else
    {
        --(this->m_head);
    }

    if (this->m_rows < TrainScheduleModelView::MAX_TRAIN_SCHEDULE_SIZE)
    {
        ++(this->m_rows);
    }

    emit dataChanged(this->index(0, 0),
                     this->index(TrainScheduleModelView::MAX_TRAIN_SCHEDULE_SIZE-1,
                                 TrainScheduleModelView::COLUMNS_AMOUNT - 1));
}

案子沒有徹底破案。 我想在 Ubuntu 或應用程序的初始化代碼上移植 Qt 可能存在問題。

更新我找到了泄漏源。 queryAccessibleInterface函數返回分配有新指針和對它的代碼松散引用。

void QAbstractItemViewPrivate::_q_layoutChanged()
{
    doDelayedItemsLayout();
#ifndef QT_NO_ACCESSIBILITY
#ifdef Q_WS_X11
    Q_Q(QAbstractItemView);
    if (QAccessible::isActive()) {
        QAccessible::queryAccessibleInterface(q)->table2Interface()->modelReset();
        QAccessible::updateAccessibility(q, 0, QAccessible::TableModelChanged);
    }
#endif
#endif
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM