本文是 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(); }