Skip to content

Fix: Group deletion exception#523

Closed
JWWTSL wants to merge 0 commit into
linuxdeepin:masterfrom
JWWTSL:master
Closed

Fix: Group deletion exception#523
JWWTSL wants to merge 0 commit into
linuxdeepin:masterfrom
JWWTSL:master

Conversation

@JWWTSL
Copy link
Copy Markdown
Contributor

@JWWTSL JWWTSL commented Apr 21, 2026

Log: Optimized group processing logic
PMS: bug-358193

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: JWWTSL

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

以下是对提供的 Git diff 的详细代码审查,包括语法逻辑、代码质量、代码性能和代码安全方面的分析。

1. 文件:src/remotemanage/groupconfigoptdlg.cppgroupconfigoptdlg.h

变更概述
GroupConfigOptDlg 类中添加了 m_originalGroupName 成员变量,并在确认按钮的点击事件中增加了逻辑,用于处理空分组的添加以及重命名分组后清理旧空分组的逻辑。这主要是为了修复 BUG 355415。

代码逻辑与质量分析

  1. 成员变量初始化

    • 代码m_originalGroupName(groupName)
    • 审查意见良好。在构造函数初始化列表中正确初始化了新成员变量。
  2. 空分组处理逻辑

    • 代码
      QString groupName = m_groupNameEdit->text().trimmed();
      QMap<QString, QList<ServerConfig *>> &serverConfigs = ServerConfigManager::instance()->getServerConfigs();
      if (!serverConfigs.contains(groupName)) {
          serverConfigs[groupName] = QList<ServerConfig *>();
      }
    • 审查意见
      • 逻辑正确性:这段逻辑确保了即使用户没有勾选任何服务器,只要输入了分组名并点击确认,该分组就会被创建(作为一个空列表)。
      • 代码质量:使用 trimmed() 是很好的做法,防止了首尾空格导致的意外分组创建。
  3. 重命名分组清理逻辑

    • 代码
      if (!m_originalGroupName.isEmpty() && m_originalGroupName != groupName) {
          if (serverConfigs.contains(m_originalGroupName) && serverConfigs[m_originalGroupName].isEmpty()) {
              serverConfigs.remove(m_originalGroupName);
          }
      }
    • 审查意见
      • 逻辑正确性:当编辑现有分组且名称改变时,如果旧分组名下没有服务器了(即列表为空),则移除该键值对。这防止了产生无用的空分组残留。
      • 潜在问题:这段代码假设 ServerConfigManager 中的数据在对话框打开后没有被外部修改。如果这是一个单例且可能在多线程环境下使用,直接引用返回值可能存在线程安全问题(见下文安全部分)。

代码安全分析

  • 引用返回值的并发访问
    • 代码获取了 ServerConfigManager::instance()->getServerConfigs() 的引用。如果 ServerConfigManager 是跨线程使用的单例,直接持有并在 UI 线程中修改这个引用的数据结构(QMap)是不安全的。Qt 容器类通常不是线程安全的。
    • 建议:确认 ServerConfigManager 的使用场景。如果仅限 UI 线程,则当前写法没问题。如果涉及多线程,应考虑加锁或提供线程安全的封装接口(如 addGroup/renameGroup)。

2. 文件:src/remotemanage/remotemanagementpanel.cpp

变更概述
RemoteManagementPanel::initUI 中,为按钮设置了焦点策略,并显式定义了 Tab 键的焦点顺序。

代码逻辑与质量分析

  1. 焦点策略设置

    • 代码
      m_addGroupButton->setFocusPolicy(Qt::TabFocus);
      m_pushButton->setFocusPolicy(Qt::TabFocus);
    • 审查意见良好。显式设置 Qt::TabFocus 确保了这些按钮只能通过 Tab 键获取焦点,而不是通过鼠标点击。这有助于键盘导航的一致性。
  2. Tab 顺序设置

    • 代码
      setTabOrder(m_searchEdit->lineEdit(), m_listWidget);
      setTabOrder(m_listWidget, m_pushButton);
      setTabOrder(m_pushButton, m_addGroupButton);
    • 审查意见
      • 逻辑正确性:显式设置 Tab 顺序符合用户的视觉浏览顺序(搜索 -> 列表 -> 添加按钮 -> 添加分组按钮)。
      • 代码质量:这是一种提升可访问性(Accessibility)的好做法。

3. 文件:src/remotemanage/serverconfigmanager.cpp

变更概述
delServerGroupConfig 函数中,修复了迭代器失效的问题,并确保了分组条目被彻底删除。

代码逻辑与质量分析

  1. 迭代器失效修复

    • 代码
      const QList<ServerConfig *> configsCopy = m_serverConfigs[key];
      for (ServerConfig *config : configsCopy) {
          // ... 逻辑 ...
      }
    • 审查意见优秀
      • 问题背景:原代码直接遍历 m_serverConfigs[key],而在循环内部调用了 delServerConfig。如果 delServerConfig 内部修改了 m_serverConfigs[key](例如移除了元素),会导致迭代器失效,引发崩溃。
      • 解决方案:通过 configsCopy 创建了一个常量副本进行遍历,这是处理此类问题的标准且安全的方法。
  2. 确保删除分组键

    • 代码
      m_serverConfigs.remove(key);
    • 审查意见必要且正确。在循环结束后显式调用 remove,确保无论分组是否为空(理论上循环处理完所有元素后应为空),该键都会从 Map 中移除。

代码性能分析

  • 深拷贝开销
    • QList<ServerConfig *> configsCopy = ... 执行的是指针列表的浅拷贝(复制指针值,不复制对象),开销很小。
    • 如果 ServerConfig 对象本身很大且这里发生了深拷贝,则需要关注性能,但此处是指针列表,性能影响可忽略。

代码安全分析

  • 内存管理
    • 循环中创建了 new ServerConfig 并传递给 saveServerConfig。需要确保 saveServerConfig 正确接管了这些对象的所有权,且没有内存泄漏。
    • delServerConfig 被调用时,需要确认它是否正确释放了旧 config 的内存。

总结与改进建议

总体而言,这次代码变更质量很高,逻辑清晰,修复了潜在的崩溃风险(迭代器失效)和功能缺陷(空分组处理)。

主要改进建议

  1. 线程安全

    • 检查 ServerConfigManager 的使用场景。如果它是跨线程共享的单例,建议不要直接暴露 getServerConfigs() 返回内部容器的引用。这破坏了封装性并导致并发修改风险。
    • 改进建议:将分组操作逻辑(创建空分组、重命名分组、删除空分组)封装到 ServerConfigManager 的成员函数中,例如 ServerConfigManager::ensureGroupExists(const QString &name)ServerConfigManager::renameGroup(const QString &oldName, const QString &newName)。在 Manager 内部统一处理数据修改和加锁(如果需要)。
  2. 逻辑封装

    • groupconfigoptdlg.cpp 中,直接操作 serverConfigs 的 Map 使得业务逻辑分散到了 UI 层。
    • 改进建议:将以下逻辑移入 ServerConfigManager
      // 建议封装到 ServerConfigManager 中
      void ServerConfigManager::updateGroupConfig(const QString &oldName, const QString &newName) {
          QMutexLocker locker(&m_mutex); // 如果需要加锁
          // ... 处理空分组创建和旧分组清理的逻辑 ...
      }
      UI 层只需调用 ServerConfigManager::instance()->updateGroupConfig(m_originalGroupName, groupName)
  3. 常量引用

    • delServerGroupConfig 中,configsCopy 可以声明为 const auto &(虽然 QList 的隐式共享机制使得按值传递也很高效,但显式引用更符合直觉)。
    • 修正:const auto &configsCopy = m_serverConfigs[key]; 是更好的写法,避免引用计数的原子操作开销(尽管很小)。
  4. 空字符串检查

    • groupconfigoptdlg.cpp 中,创建分组前应检查 groupName 是否为空字符串。
    • 改进建议
      QString groupName = m_groupNameEdit->text().trimmed();
      if (groupName.isEmpty()) {
          // 处理错误,例如显示提示信息并返回,不执行 accept()
          return;
      }
  5. 资源管理

    • 确认 ServerConfig 的拷贝构造函数行为。代码中使用了 *newConfig = *config;。如果 ServerConfig 包含指针成员且未实现深拷贝,可能会导致双重释放或内存泄漏。建议审查 ServerConfig 类的实现。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants