Qt 4.8 endInsert / RemoveRows вызывают утечку памяти? - PullRequest
1 голос
/ 01 апреля 2020

enter image description here Недавно я провел несколько стресс-тестов для своего приложения Qt 4.8. Я видел с помощью инструмента массива valgrind, что он вызывает расширение кучи памяти ...

Используя этот инструмент, я обнаружил, что эта память выделяется этой трассировкой стека (это другой вызов массива, поэтому значения отличаются от один на скриншоте):

->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 Ответ

0 голосов
/ 15 апреля 2020

У меня было две попытки решить эту проблему:

  1. Сначала я попытался исключить модуль Accesibility - я надеялся, что в этом нет необходимости. Мне пришлось собрать Qt из исходного кода с опцией ./configure ... -no-accessibility.... Дело было решено, но пользовательский интерфейс приложения резко пострадал. Я не смог ввести пароль, потому что клавиатура была заблокирована. Поэтому это решение было неприемлемым.
  2. Следующим обходным решением было устранение вставки динамических c строк. Я изменил подход и вместо эмуляции вставки строк, я возвращаю всегда фиксированное количество строк (отображались пустые строки, однако внутри данных не было). Когда я помещаю некоторые данные в таблицу, я посылаю сигнал 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));
}

Дело не полностью раскрыто. Я предполагаю, что может быть проблема с портированием Qt на Ubuntu или код инициализации приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...