Qt QTreeWidget控件造成程序不响应,内存泄露

有道词典导致Qt程序卡死的问题我已经发现了一段时间,之前以为是自己程序的问题,后面多方验证才发现这个问题是我更新到Qt5.12后产生的。

下面是该bug的重现条件:

1.打开有道词典,将屏幕取词开关打开

Qt QTreeWidget控件造成程序不响应,内存泄露_第1张图片

2.在自己的程序中添加一个QTreeView或者QTreeWidget,并且添加一些数据

没错,这个bug主要是在QTreeView或QTreeWidget上引发,其他控件我还没有发现存在该问题。我这里就使用Qt的帮助文档软件来测试:
Qt QTreeWidget控件造成程序不响应,内存泄露_第2张图片

3.将鼠标放到上面的红色框选区域中停顿1秒左右

软件卡死。打开任务管理器可以看到Qt帮助软件的内存正在疯狂增长,并且CPU居高不下:
Qt QTreeWidget控件造成程序不响应,内存泄露_第3张图片
其实,有人已经向Qt反馈了该问题https://bugreports.qt.io/browse/QTBUG-77974,不过目前这个问题还未解决。Qt的开发人员表示会在Qt5.13.2和Qt5.14上解决该问题,不过在此之前我们可以临时解决一下该问题,以下是我提供的一个临时解决方案。

临时解决方案

通过翻阅源代码发现,该问题引起的位置位于Qt底层windows部分的uiautomation模块中,而通过消息分析发现引起该问题的Windows消息为WM_GETOBJECT。修改uiautomation内的代码比较困难,并且需要编译Qt源代码,太过麻烦,因此,我选择屏蔽掉WM_GETOBJECT消息,这里是关于WM_GETOBJECT的 解释

以下是临时解决方案的代码,写在main.cpp中即可:

#include 
#include 
#include 
#include 
//QTBUG-77974
class MyFilter : public QAbstractNativeEventFilter
{
public:
	bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override
	{
		MSG* msg = (MSG*)message;
		if (msg->message == WM_GETOBJECT)
			return true;
		return false;
	}
};

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	a.installNativeEventFilter(new MyFilter);
	QTreeWidget w;
	w.exec();
	return a.exe();
}

过滤掉WM_GETOBJECT之后应用程序不会再被有道词典卡死了,等官方解决该问题后就可以删掉这段代码了。

Node: 实测Qt5.13.2版本下已解决该问题

你可能感兴趣的:(debug,qt学习)