Files
VX5_KRO_GearPump/doc/PrintSetting_Crash_Risk_Analysis.md
2026-06-30 08:21:08 +08:00

240 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PrintSetting 崩溃风险分析报告
## 涉及文件
| 文件 | 说明 |
|------|------|
| [Printsetting.h](../Printsetting.h) | `PrintSettingModel` 结构体 + `PrintSetting` 类声明 |
| [Printsetting.cpp](../Printsetting.cpp) | `PrintSetting` 类实现 + `PrintSettingModel` 静态方法实现 |
| [testprintwidget.cpp](../testprintwidget.cpp) | `TestPrintWidget` 中调用 `m_printSetting` 的代码 |
| [InkJetPrinter.cpp](../InkJetPrinter.cpp) | `InkJetPrinter` 中使用 `m_PrintSetting` 的代码 |
---
## 🔴 高风险(必定崩溃)
### 1. `applyPrintSettingsToSysPara()` — `sysPara->devOp` 在 if 保护块外被访问
**文件**: [Printsetting.cpp:600-609](../Printsetting.cpp#L600-L609)
```cpp
void PrintSetting::applyPrintSettingsToSysPara(bool showTip)
{
updateModelFromUI();
PrintSettingModel::applyToSysPara(m_model, sysPara); // L600: 无 null 检查
if (sysPara) { // L602: 有检查
sysPara->devOp->setHighVoltageAmplitudetoSTM32();
sysPara->devOp->writeFpgaCalandar(0);
sysPara->devOp->writeFlightCompCtrl(...);
}
if(sysPara->devOp->writeFpgaPrintPara(true) != -1 && showTip) { // L609: ❌ 在 if(sysPara) 之外!
QMessageBox box(...);
box.exec();
}
if(sysPara)
sysPara->saveParaToFile();
}
```
**问题**:
- L600 调用 `PrintSettingModel::applyToSysPara(m_model, sysPara)` 时未检查 `sysPara` 是否为 null。
- L609 的 `sysPara->devOp->writeFpgaPrintPara(true)` 在 `if(sysPara)` 保护块**之外**,如果 `sysPara` 为 null,直接崩溃。
- L602-L606 虽在 `if(sysPara)` 内,但 `sysPara->devOp` 本身也可能为 null。
**触发场景**:`bindSysPara()` 未被调用或 `sysPara` 被意外置空时,用户点击"应用"按钮。
---
### 2. `PrintSettingModel::applyToSysPara()` — `sysPara` 参数无 null 检查
**文件**: [Printsetting.cpp:743-799](../Printsetting.cpp#L743-L799)
```cpp
void PrintSettingModel::applyToSysPara(const PrintSettingModel &model, SysPara *sysPara)
{
sysPara->para.leftRightInverse = model.leftRightInverse; // ❌ 无 null 检查
sysPara->para.upDownInverse = model.upDownInverse;
// ... 后续约 30 行全部直接访问 sysPara->para.xxx
}
```
**问题**:整个函数体没有对 `sysPara` 做 null 检查,直接解引用。如果传入 null,立即崩溃。
**调用链**:
- `PrintSetting::applyPrintSettingsToSysPara()` → `PrintSettingModel::applyToSysPara(m_model, sysPara)`
- `PrintSetting::bindSysPara()` → `PrintSettingModel::fromSysPara(sysPara)` (同样无 null 检查,见下文)
---
### 3. `PrintSettingModel::fromSysPara()` — `sysPara` 参数无 null 检查
**文件**: [Printsetting.cpp:802-845](../Printsetting.cpp#L802-L845)
```cpp
PrintSettingModel PrintSettingModel::fromSysPara(SysPara *sysPara)
{
PrintSettingModel model;
model.leftRightInverse = sysPara->para.leftRightInverse; // ❌ 无 null 检查
model.upDownInverse = sysPara->para.upDownInverse;
// ... 后续约 30 行全部直接访问 sysPara->para.xxx
}
```
**问题**:与 `applyToSysPara()` 相同,整个函数体没有对 `sysPara` 做 null 检查。
**调用链**:
- `PrintSetting::bindSysPara()` → `PrintSettingModel::fromSysPara(sysPara)`
---
### 4. `on_pushButtonApplyPulseFix_clicked()` — `sysPara` 可能为 null
**文件**: [Printsetting.cpp:287-290](../Printsetting.cpp#L287-L290)
```cpp
void PrintSetting::on_pushButtonApplyPulseFix_clicked()
{
pulseNumFix->bindSysPara(sysPara); // ❌ sysPara 可能为 null
pulseNumFix->hide();
pulseNumFix->show();
}
```
**问题**:未检查 `sysPara` 是否为 null,直接传给 `pulseNumFix->bindSysPara()`。
---
### 5. TestPrintWidget 中 `m_printSetting` 空指针解引用(3处)
已在 [TestPrintWidget 崩溃风险分析报告](./TestPrintWidget_Crash_Risk_Analysis.md) 中详述,此处汇总:
| 位置 | 代码 | 问题 |
|------|------|------|
| [testprintwidget.cpp:435](../testprintwidget.cpp#L435) | `PrintSettingModel::saveToXml(m_printSetting->model(), writer)` | `m_printSetting` 可能为 null |
| [testprintwidget.cpp:621-622](../testprintwidget.cpp#L621-L622) | `m_printSetting->setModel(model)` / `m_printSetting->applyPrintSettingsToSysPara(false)` | `m_printSetting` 可能为 null |
| [testprintwidget.cpp:1122](../testprintwidget.cpp#L1122) | `m_printSetting->setModel(defModel)` | `m_printSetting` 可能为 null |
---
## 🟡 中风险(特定条件下崩溃)
### 6. `applyPrintSettingsToSysPara()` — `sysPara->devOp` 可能为 null
**文件**: [Printsetting.cpp:603-606](../Printsetting.cpp#L603-L606)
```cpp
if (sysPara) {
sysPara->devOp->setHighVoltageAmplitudetoSTM32(); // devOp 可能为 null
sysPara->devOp->writeFpgaCalandar(0); // devOp 可能为 null
sysPara->devOp->writeFlightCompCtrl(...); // devOp 可能为 null
}
```
**问题**:虽然检查了 `sysPara`,但 `sysPara->devOp` 指针本身可能为 null(取决于 `SysPara` 的初始化时机)。
---
### 7. `on_checkEyeTriggerSynPrintEn_clicked()` — `sysPara` 有检查但 `comboBoxSyncActType` 可能越界
**文件**: [Printsetting.cpp:302-340](../Printsetting.cpp#L302-L340)
```cpp
void PrintSetting::on_checkEyeTriggerSynPrintEn_clicked(bool checked)
{
if(sysPara) // ✅ 有 null 检查
{
// ...
if(ui->comboBoxSyncActType->currentIndex() >= ui->comboBoxSyncActType->count()
|| ui->comboBoxSyncActType->currentIndex() == -1)
{
ui->comboBoxSyncActType->setCurrentIndex(0);
}
}
}
```
**问题**:`comboBoxSyncActType` 的 `currentIndex()` 值为 -1 时的处理是正确的,但如果 comboBox 未正确初始化(count() 为 0),`setCurrentIndex(0)` 可能无效,但不会崩溃。此处理论上安全,标注为中风险仅供参考。
---
## 🟢 低风险(逻辑瑕疵,不太可能崩溃)
### 8. `PrintSettingModel::toString()` — 格式说明符类型不匹配
**文件**: [Printsetting.cpp:849-856](../Printsetting.cpp#L849-L856)
```cpp
QString PrintSettingModel::toString(const PrintSettingModel &model)
{
QString str = QString::asprintf("LRInverse: %d, ... triggerInterval: %d, ... eleEyeRepeatCnt: %d, ...",
model.triggerInterval, ... model.eleEyeRepeatCnt, ...);
}
```
**问题**:`model.triggerInterval` 和 `model.eleEyeRepeatCnt` 是 `unsigned` 类型,但格式说明符用了 `%d`(有符号)。不会崩溃,但可能输出异常值(如大数字显示为负数)。
---
### 9. `PrintSettingModel::defPrintSettingModel()` — 文件不存在时静默返回默认值
**文件**: [Printsetting.cpp:860-873](../Printsetting.cpp#L860-L873)
```cpp
PrintSettingModel PrintSettingModel::defPrintSettingModel()
{
QFile file(DEF_PRINT_SETTINGS_PATH);
if (!file.open(QIODevice::ReadOnly)) {
return PrintSettingModel(); // 静默返回默认构造
}
// ...
}
```
**问题**:文件打开失败时没有日志输出,不利于调试。不会崩溃。
---
### 10. `updateModelFromUI()` — 无返回值校验
**文件**: [Printsetting.cpp:114-170](../Printsetting.cpp#L114-L170)
```cpp
m_model.encoderPulsePerMm = ui->lineEditTriggerPulsePerMm->text().toFloat();
```
**问题**:`toFloat()` 在输入为空时返回 0.0,不会崩溃。但如果用户输入了非法字符(虽然有 `QDoubleValidator`),结果可能不符合预期。
---
### 11. `on_radioButtonEleEyeLevelTrigger_pressed()` 等函数中 `setEnableSynTriggerSetting` 的判断逻辑
**文件**: [Printsetting.cpp:310-325](../Printsetting.cpp#L310-L325)
```cpp
void PrintSetting::on_radioButtonEleEyeEdgetTrigger_pressed()
{
setTriggerUI(PRINT_TRIGGER_ELEC_EYE_EDGE);
if(ui->radioButtonSynTriggerExternal->isChecked())
setEnableSynTriggerSetting(true);
else
setEnableSynTriggerSetting(false);
}
```
**问题**:这些函数未检查 `sysPara` 是否为 null 就调用 `setTriggerUI`,但 `setTriggerUI` 只操作 `m_model` 和 UI 控件,不依赖 `sysPara`,所以安全。
---
## 📋 修复建议汇总
| 优先级 | 位置 | 问题 | 修复方案 |
|--------|------|------|----------|
| **P0** | `applyPrintSettingsToSysPara()` L600 | `sysPara` 未检查就传给 `applyToSysPara` | 在 L600 前加 `if(!sysPara) return;` |
| **P0** | `applyPrintSettingsToSysPara()` L609 | `sysPara->devOp` 在 if 块外访问 | 将 L609-L614 移入 `if(sysPara)` 块内 |
| **P0** | `PrintSettingModel::applyToSysPara()` L743 | `sysPara` 无 null 检查 | 函数开头加 `if(!sysPara) return;` |
| **P0** | `PrintSettingModel::fromSysPara()` L802 | `sysPara` 无 null 检查 | 函数开头加 `if(!sysPara) return PrintSettingModel();` |
| **P0** | `on_pushButtonApplyPulseFix_clicked()` L287 | `sysPara` 未检查 | 加 `if(!sysPara) return;` |
| **P1** | `applyPrintSettingsToSysPara()` L603 | `sysPara->devOp` 可能 null | 加 `if(sysPara->devOp)` 判断 |
| **P1** | `testprintwidget.cpp` 多处 | `m_printSetting` 可能 null | 加 `if(m_printSetting)` 判断(共3处) |
---
## 崩溃调用链总结
```
用户点击"应用"按钮
→ PrintSetting::on_pushButtonApply_pressed()
→ PrintSetting::applyPrintSettingsToSysPara(true)
→ PrintSettingModel::applyToSysPara(m_model, sysPara) ← ❌ sysPara 可能 null
→ sysPara->devOp->writeFpgaPrintPara(true) ← ❌ 在 if(sysPara) 外
```
```
用户点击"脉冲修正"按钮
→ PrintSetting::on_pushButtonApplyPulseFix_clicked()
→ pulseNumFix->bindSysPara(sysPara) ← ❌ sysPara 可能 null
```
```
加载/新建文件
→ TestPrintWidget::saveFile() / parseVbfile() / on_newfileButton_pressed()
→ m_printSetting->model() / setModel() / applyPrintSettingsToSysPara() ← ❌ m_printSetting 可能 null
```
---
## 生成时间
2026-06-29