Сигнал Qt все еще срабатывает после удаления QObject - PullRequest
0 голосов
/ 09 июня 2019

У меня есть программа на C ++, использующая Qt, с графическим интерфейсом QObject, у которого есть ComboBox (назовем его foo), связанный с функцией (bar()).Этот объект QObject называется object A.

Поле со списком связано в конструкторе:

  connect(foo, SIGNAL(currentIndexChanged(int)), SLOT(bar(int)));

В bar(int) эта функция вызывается в конце функции:

  inspector->update();

В функции инспектора update это происходит:

  • A удалено (delete A;, в значительной степени - оно было создано с помощью new).

  • Создан новый экземпляр того же типа, что и A, назовем его объектом B.

Thisинициализируется и на мгновение работает нормально, а затем все идет ужасно неправильно.

Ошибка программы, но только из-за ошибки Qt.GDB мало помогает, но запуск программы через Valgrind memcheck производит поток недопустимых операций чтения, таких как:

==23410== Invalid read of size 8
==23410==    at 0xFE92D7A: QMetaObject::activate(QObject*, int, int, void**) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.9.5)
==23410==    by 0x79DDC94: QComboBox::currentIndexChanged(QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.9.5)
==23410==    by 0x79DFB2D: ??? (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.9.5)
...
==23410==  Address 0x3218ca68 is 8 bytes inside a block of size 48 free'd
==23410==    at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23410==    by 0xFE9119A: QObjectPrivate::deleteChildren() (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.9.5)
==23410==    by 0x7913D4B: QWidget::~QWidget() (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.9.5)

Мне кажется, что сигнал с foo снова отправляется, ипытается вызвать bar() объекта A, который не существует.Но как это возможно?Конечно, delete A также должен помешать прохождению каких-либо сигналов?Кроме того, я только один раз изменяю значение поля со списком - зачем отправлять несколько сигналов?

Я пробовал блокировать сигналы и пытался изменить порядок, но безуспешно.

Вот весь соответствующий Журнал памяти Valgrind .

Это ошибка с Qt?Или я что-то не так делаю?Любая помощь, включая дальнейшую отладку, очень ценится.

1 Ответ

0 голосов
/ 09 июня 2019

Попробуйте сделать это:

  • Сначала добавьте члена QMetaObject::Connection foo_barConnect; в свой класс.

  • В конструкторе сохраните свой connect in foo_barConnect:

foo_barConnect = connect(foo, SIGNAL(currentIndexChanged(int)), SLOT(bar(int)));
  • В функции update() перед delete добавить:
// Check if `foo_barConnect` is valid (connected)
if(foo_barConnect){
    // Disconnect foo_bar connection
    disconnect(foo_barConnect);
}
  • Если вы повторно new объект и вам нужно соединение, не забудьте повторно connect и сохранить соединение в foo_barConnect.

Надеюсь, это поможет вам.

...