当前位置: 首页 > web >正文

插件热更新后界面不更新问题

开发环境

            操作系统 : Linuxqt版本  : qt5

背景

         在开发qt插件的过程中发现的,原本是想做一个插件热插拔的功能,作用是在主程序不关闭的情况下,替换同名称的插件共享库并生效

         但在自测的时候发现,替换了共享库之后发现新库的内容并没有生效

问题排查过程

          我是使用QPluginLoader去实现qt插件,这样可以直接导出类,方便主程序加载调用

          https://gitee.com/learninglzq/qt-use-problem/tree/master/hot-test-code

          在发现替换共享库不生效后,我首先是设置环境变量QT_DEBUG_PLUGINS=1没有什么异常输出,接着我思考了一下,加载库不生效也是是qt接口用的不对,加载接口如下:

            bool QPluginLoader::load() //加载QLibrary::LoadHints QPluginLoader::loadHints() const //设置加载标志

           load接口在底层调用的是dlopen函数,loadHints设置的参数会影响调用dlopen时的传参

     QLibrary::PreventUnloadHint参数对应的是dlopen的RTLD_NODELETE标志

           所以我调用loadHints函数时,仅传参QLibrary::ResolveAllSymbolsHint避免其他参数影响

结果发现替换后还是没有效果,无奈只能去社区提问了,大佬们建议我试试设置LD_DEBUG环境变量,看看输出,果然是发现了有异常输出

89768:    file=libQt5Sql.so.5 [0];  needed by /home/lzq/hot-plugin/testmain/libxxx.so [0]
89768:    file=libQt5Sql.so.5 [0];  generating link map
89768:      dynamic: 0x00007fb9b8b30cd0  base: 0x00007fb9b8af0000   size: 0x00000000000416c8
89768:        entry: 0x00007fb9b8af0000  phdr: 0x00007fb9b8af0040  phnum:                  9
89768:    
89768:    activating NODELETE for /home/lzq/hot-plugin/testmain/libxxx.so [0]

            activating NODELETE这个字段很值得怀疑,因为和RTLD_NODELETE很像,看看是什么意思

            activating NODELETE 表示动态链接器(ld.so)为某个共享库启用了NODELETE标志,强制该库在程序运行期间不被卸载‌,即使其引用计数归零。此机制用于确保关键库的稳定性,防止意外卸载导致程序崩溃或资源泄漏。

          因为出问题的工程中业务代码太多,不知道是哪部分影响的,我自己又写了一个demo进行比较,发现替换库正确且没有出现activating NODELETE

          接着我在网上查了一下可能会出现activating NODELETE标记的原因

            (1) dlopen上显示的使用 RTLD_NODELETE(2) 其他模块使用了插件库中的符号,资源未释放(可能释放了也会被标记NODELETE)(3) 内联函数可能导致被标记

           知道了可能会产生的原因,但不知道哪部分代码导致的,这就很难受,只能祭出二分法删代码来确定,发现QDBusInterface::call会导致NODELTE,最后还是在社区上了解到,QDBus模块中有使用内联函数

修改方法

       网上、社区上、公司的人都问完了,没有明确的线索

       我只能独自思考,在考虑到跨模块引用其他符号可能到导致NODELETE时,我突然想到linux下默认符号是不隐藏的,主程序是我实现的,就是调用了一个导出类的接口,没有别的,也许加载库时用某些底层的东西引用了吧

       总之,我想到了使用g++编译参数隐藏不需要导出的符号,解决了这个问题

http://www.xdnf.cn/news/1861.html

相关文章:

  • Flutter 环境搭建 (Android)
  • 雷达水位计在山洪预警中的作用
  • Babylon.js 材质统一转换指南:将 AssetContainer 中的所有材质转换为 PBRMetallicRoughnessMaterial
  • 【Python-Day 5】Python 格式化输出实战:%、format()、f-string 对比与最佳实践
  • 测试流程?
  • Python3(11) 字典
  • Java学习手册:Java时间类使用
  • 16:00开始面试,16:08就出来了,问的问题有点变态。。。
  • react 常用钩子 hooks 总结
  • 《Keras 3 :使用 TFServing 提供 TensorFlow 模型》
  • Linux中你必须掌握的20个常见命令,提升工作效率!
  • 问答页面支持拖拽和复制粘贴文件,MaxKB企业级AI助手v1.10.6 LTS版本发布
  • conformer编码器
  • DeskGo 4.0(官方版)桌面管理工具软件下载及安装教程
  • JDBC之ORM思想及SQL注入
  • UWA DAY 2025 正式启动|十年筑基,驱动游戏未来引擎
  • Kubernetes 节点 Not Ready 时 Pod 驱逐机制深度解析(上)
  • Web漏洞--XSS之订单系统和Shell箱子
  • Android APP 热修复原理
  • ArrayUtils:数组操作的“变形金刚“——让你的数组七十二变
  • python实现简单的UI交互
  • RT Thread 发生异常时打印输出cpu寄存器信息和栈数据
  • C++11介绍
  • 【阿里云大模型高级工程师ACP习题集】2.5 优化RAG应用提升问答准确度(⭐️⭐️⭐️ 重点章节!!!)
  • C++面试复习日记(8)2025.4.25,malloc,free和new,delete的区别
  • Maven基础、HTTP协议、请求响应(Web后端笔记第一期)
  • 策略模式(Strategy Pattern)详解
  • 深度学习--自然语言处理统计语言与神经语言模型
  • 打造高功率、高电流和高可靠性电路板的厚铜PCB生产
  • 基于STM32的温室环境智能调控系统仿真(仿真+代码)