多显示器配置变更时Qt应用因glWaitSync访问冲突崩溃
崩溃原因分析
- Qt 5.15.2 ANGLE后端已知缺陷:Qt 5.15.2版本中,ANGLE后端处理显示配置变更(跨DPI显示器移动窗口、分辨率调整)时,D3D11设备重置逻辑存在bug。当系统触发
DXGI_ERROR_DEVICE_REMOVED(设备被移除)信号时,ANGLE未能正确清理或重建同步对象,导致后续调用glWaitSync时出现内存访问违规(ACCESS_VIOLATION)。 - 跨DPI上下文同步失效:QWebEngineView的父控件绑定到主显示器的
ui.widgetPms,窗口跨不同DPI显示器移动后,Qt的DPI缩放上下文与ANGLE的D3D11设备上下文不同步,设备重置时资源引用失效,触发崩溃。
解决方案
1. 升级Qt版本(优先推荐)
Qt 5.15.3及后续补丁版本(如5.15.12)修复了多个QWebEngine与ANGLE后端相关的显示配置变更崩溃问题。若无法迁移到Qt 6,建议升级到Qt 5.15系列的最新稳定补丁版。
2. 切换到桌面OpenGL后端
强制应用使用桌面OpenGL替代ANGLE,规避D3D11设备重置的兼容性问题:
- 在
QApplication实例化之前添加代码:#include <QCoreApplication> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL); // 强制使用桌面OpenGL QApplication a(argc, argv); // ... 其他业务代码 return a.exec(); } - 或通过环境变量设置:启动应用前配置
QT_OPENGL=desktop
3. 监听显示变更事件,重建QWebEngineView
检测到显示配置变更时,手动销毁并重建QWebEngineView,避免无效资源引用:
- 在
PmsDialogWidget中添加监听与重建逻辑:
注意:此方法会丢失WebView当前状态(如页面内容、表单数据),需根据业务需求添加状态保存与恢复逻辑。// PmsDialogWidget.h class PmsDialogWidget : public QWidget { Q_OBJECT private slots: void recreateWebView(); private: QWebEngineView* webView = nullptr; QWebChannel* webChannel = nullptr; // ... 其他成员变量 }; // PmsDialogWidget.cpp PmsDialogWidget::PmsDialogWidget(QWidget* parent) : QWidget(parent) { ui.setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_StyledBackground, true); connect(this, &QWidget::screenChanged, this, &PmsDialogWidget::recreateWebView); recreateWebView(); // 首次初始化 } void PmsDialogWidget::recreateWebView() { // 销毁原有控件 delete webView; delete webChannel; // 重新创建并初始化 webView = new QWebEngineView(ui.widgetPms); webChannel = new QWebChannel(ui.widgetPms); // 恢复WebView状态(如加载URL、绑定WebChannel等) webView->page()->setWebChannel(webChannel); // webView->load(QUrl("your-target-url")); }
4. 调整高DPI缩放策略
- 禁用高DPI缩放(妥协方案,高分辨率显示器上界面会模糊):
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); - 或强制使用系统级DPI缩放:
确保所有显示器使用相同缩放比例,可减少跨DPI场景的冲突。QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
5. 更新显卡驱动
NVIDIA旧版本驱动可能存在D3D11设备重置的兼容性问题,将RTX 750i的驱动更新到最新稳定版,可解决部分DXGI_ERROR_DEVICE_REMOVED触发的崩溃。
内容的提问来源于stack exchange,提问作者wenshu wu
相关产品推荐
相关产品推荐

