94 lines
3.9 KiB
Markdown
94 lines
3.9 KiB
Markdown
# BarcodeEditor 健壮性分析报告
|
||
|
||
## 涉及文件
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| [scene/BarcodeEditor.h](../scene/BarcodeEditor.h) | `BarcodeViewModel` 结构体 + `BarcodeEditor` 类声明 |
|
||
| [scene/BarcodeEditor.cpp](../scene/BarcodeEditor.cpp) | `BarcodeEditor` 类实现 |
|
||
|
||
---
|
||
|
||
## 🔴 高风险(必定崩溃)
|
||
|
||
### 1. `applyCounterConfigToSysPara()` — `m_sysPara->devOp` 无 null 检查
|
||
**文件**: [BarcodeEditor.cpp:260](../scene/BarcodeEditor.cpp#L260)
|
||
```cpp
|
||
m_sysPara->devOp->writeFpgaCalandar(0);
|
||
```
|
||
**问题**:函数开头已经检查 `if (!m_sysPara) return;`,但 `m_sysPara` 不为 null 不代表 `m_sysPara->devOp` 不为 null。`devOp` 仍可能为 null,此时直接访问会崩溃。
|
||
|
||
---
|
||
|
||
## 🟡 中风险(特定条件下逻辑错误)
|
||
|
||
### 2. `BarcodeViewModel::saveToXml()` — `QVariant::value<T>()` 类型不一致
|
||
**文件**: [BarcodeEditor.cpp:515-534](../scene/BarcodeEditor.cpp#L515-L534)
|
||
```cpp
|
||
if(vm.type == BARCODE_TYPE_BARCODE) {
|
||
DlgBarcodeFormatVM barcodeFormat = vm.format.value<DlgBarcodeFormatVM>();
|
||
// ...
|
||
}
|
||
else {
|
||
DlgQrcodeFormatVM qrcodeFormat = vm.format.value<DlgQrcodeFormatVM>();
|
||
// ...
|
||
}
|
||
```
|
||
**问题**:如果 `vm.type` 与 `vm.format` 中实际存储的类型不一致,`QVariant::value<T>()` 会返回默认构造对象,不会崩溃但会导致数据丢失。QVariant 本身保证不崩溃。
|
||
|
||
---
|
||
|
||
### 3. `bindViewModel()` 和 `onContentChanged()` — `m_sysPara` 可能为 null 传给 `makeCounterVM`
|
||
**文件**: [BarcodeEditor.cpp:135-140](../scene/BarcodeEditor.cpp#L135-L140) 和 [BarcodeEditor.cpp:467-472](../scene/BarcodeEditor.cpp#L467-L472)
|
||
```cpp
|
||
m_counterEditor->setViewModel(makeCounterVM(m_sysPara, ...));
|
||
```
|
||
**问题**:`m_sysPara` 可能为 null(`bindSysPara()` 未被调用时),虽然 `makeCounterVM` 内部已有 `if(!sysPara) return vm;` 保护,不会崩溃,但返回的空 VM 可能导致计数器显示不正确。
|
||
|
||
---
|
||
|
||
## 🟢 低风险(健壮性瑕疵,不会崩溃)
|
||
|
||
### 4. 构造函数中 `m_dateFormatEditor` / `m_dateReplaceEditor` / `m_counterEditor` 未设置 parent
|
||
**文件**: [BarcodeEditor.cpp:50-55](../scene/BarcodeEditor.cpp#L50-L55)
|
||
```cpp
|
||
m_dateFormatEditor = new DateFormatEditor();
|
||
m_dateReplaceEditor = new DateReplaceEditor();
|
||
m_counterEditor = new CounterEditor();
|
||
```
|
||
析构中手动 delete,不会内存泄漏。但无 parent 意味着 Qt 父子对象机制不适用,需确保析构顺序正确。
|
||
|
||
---
|
||
|
||
## 已经做得好的地方
|
||
|
||
- ✅ `bindSysPara()` 对 null 输入有检查 + 日志输出
|
||
- ✅ `applyCounterConfigToSysPara()` 对 `m_sysPara` null 有检查 + 日志输出
|
||
- ✅ `m_dateFormatEditor` / `m_dateReplaceEditor` / `m_counterEditor` 在构造中 new,析构中 delete,内存管理正确
|
||
- ✅ 删除标签页使用 `indexOf()` 检查 `-1` 后才移除,不会 remove 不存在的 tab
|
||
- ✅ `makeCounterVM()` 对 `sysPara` null 有检查,返回默认构造的 VM
|
||
- ✅ `eventFilter` 中对 `cursor < 0` 做了检查
|
||
- ✅ `m_barcodeFormatEditor` / `m_qrcodeFormatEditor` 作为成员变量(非指针),构造时自动初始化,永远有效
|
||
- ✅ `Q_DECLARE_METATYPE` 已声明,QVariant 类型转换安全
|
||
|
||
---
|
||
|
||
## 📋 需要修复的问题汇总
|
||
|
||
| 优先级 | 位置 | 问题 | 修复方案 |
|
||
|--------|------|------|----------|
|
||
| **P1** | `BarcodeEditor::applyCounterConfigToSysPara()` L260 | `m_sysPara->devOp` 无 null 检查 | 在访问 `devOp` 前加 `if(m_sysPara->devOp)` 保护 |
|
||
| **P2** | `bindViewModel()` L134-141 + `onContentChanged()` L466-473 | `m_sysPara` 可能为 null 传给 `makeCounterVM` | 虽然 `makeCounterVM` 自己能处理,但建议加日志或确认 `bindSysPara` 调用时机 |
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
BarcodeEditor 类的整体健壮性较好,主要问题仅有一个:
|
||
|
||
**`applyCounterConfigToSysPara()` 中 `m_sysPara->devOp` 无 null 检查**,与先前 PrintSetting 报告中发现的同类问题相同,属于 `SysPara` 中 `devOp` 指针使用的普遍模式缺陷。
|
||
|
||
---
|
||
|
||
## 生成时间
|
||
2026-06-29 |