本文是 QMainWindow上下文菜单内存泄露(QTBUG) 一文 的续篇,所以你很可能需要先看上文。
前传
问题起源于:QTBUG-7902
在Qt 4.6 下,下面的小程序在显示上下文菜单的情况下会导致程序崩溃。
#include <QApplication> #include <QTextEdit> #include <QTimer> int main(int argc, char **argv) { QApplication app(argc, argv); QTextEdit *te = new QTextEdit; te->show(); te->setText("right click here now"); QTimer ti; te->connect(&ti, SIGNAL(timeout()), te, SLOT(deleteLater())); ti.start(3000); return qApp->exec(); }
这个问题是由于QMenu::exec()开启的局部事件循环造成的副作用。【至于局部事件循环可能造成的各种潜在问题,可访问乱谈Qt事件循环嵌套】
2010.2.9日的 b7af368e86874d71ffc9071c9ef009814d6a3467 修复这个问题
修复
采用QMenu::popup() 取代 QMenu::exec()
这也是我们在 QMainWindow上下文菜单内存泄露(QTBUG) 一文中看到的 QMainWindow的上下文菜单之所以那么改动的原因。
内存泄漏
当看了 b7af368e86874d71ffc9071c9ef009814d6a3467 以后,我发现这个问题远比我想想的严重,除了QMainWindow之外,QTextEdit/QPlainTextEdit/QLineEdit/QMessageBox 等都会存在这个问题。
于是提交了 QTBUG-22817
如何修复?
也就是我们在 QMainWindow上下文菜单内存泄露(QTBUG) 一文提到的,只需要改动一行代码即可:
--- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -500,7 +500,7 @@ void QMenuPrivate::hideMenu(QMenu *menu, bool justRegi menu->blockSignals(false); #endif // QT_NO_EFFECTS if (!justRegister) - menu->hide(); + menu->close(); }