2026-06-30_18_19 缓存

This commit is contained in:
2026-07-01 08:16:05 +08:00
parent 14d97b9bcb
commit ea3c3fb234
8 changed files with 248 additions and 16 deletions
+16 -7
View File
@@ -250,6 +250,9 @@ void PrintSetting::updateSysStatusToUI(){
void PrintSetting::on_pushButtonApplyPulseFix_clicked()
{
if(!sysPara)
return;
pulseNumFix->bindSysPara(sysPara);
pulseNumFix->hide();
pulseNumFix->show();
@@ -596,22 +599,25 @@ void PrintSetting::setEnableSynTriggerSetting(bool flag){
void PrintSetting::applyPrintSettingsToSysPara(bool showTip)
{
if(!sysPara)
return;
updateModelFromUI();
PrintSettingModel::applyToSysPara(m_model, sysPara);
if (sysPara) {
if (sysPara->devOp) {
sysPara->devOp->setHighVoltageAmplitudetoSTM32();
sysPara->devOp->writeFpgaCalandar(0);
sysPara->devOp->writeFlightCompCtrl(ui->enbFlightCompCtrl->isChecked(),
ui->enbAccelDecelPredict->isChecked(), quint32(ui->flightCompWindowCycles->value()));
}
if(sysPara->devOp->writeFpgaPrintPara(true) != -1 && showTip) {
QMessageBox box(QMessageBox::Icon::Information, tr("提示"), tr("应用成功"), QMessageBox::Ok, nullptr);
auto btn = box.button(QMessageBox::Ok);
// btn->setFixedSize(80, 40);
if(sysPara->devOp->writeFpgaPrintPara(true) != -1 && showTip) {
QMessageBox box(QMessageBox::Icon::Information, tr("提示"), tr("应用成功"), QMessageBox::Ok, nullptr);
auto btn = box.button(QMessageBox::Ok);
// btn->setFixedSize(80, 40);
box.exec();
box.exec();
}
}
if(sysPara)
@@ -802,6 +808,9 @@ void PrintSettingModel::applyToSysPara(const PrintSettingModel &model, SysPara *
PrintSettingModel PrintSettingModel::fromSysPara(SysPara *sysPara)
{
PrintSettingModel model;
if(!sysPara)
return model;
model.leftRightInverse = sysPara->para.leftRightInverse;
model.upDownInverse = sysPara->para.upDownInverse;
model.mode0211 = sysPara->para.mode0211;
+5
View File
@@ -32,6 +32,11 @@ greaterThan(QT_VER_MAJ, 5) | greaterThan(QT_VER_MIN, 9) QT += serialbus
greaterThan(QT_MAJOR_VERSION, 4):QMAKE_CXXFLAGS += -fpermissive
greaterThan(QT_MAJOR_VERSION, 4):CONFIG += c++11
CONFIG += qt warn_on debug_and_release
QMAKE_CXXFLAGS += -g
#QMAKE_POST_LINK += ulimit -c unlimited
LIBS += -ldl
include(qjson/upQJson.pri)
TEMPLATE = app
+94
View File
@@ -0,0 +1,94 @@
# 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
+108
View File
@@ -1,3 +1,8 @@
#define _GNU_SOURCE // 必须放在所有头文件之前
#include <link.h> // dl_iterate_phdr 的声明
#include <dlfcn.h> // dladdr 等
#include <execinfo.h> // backtrace
#include <QApplication>
#include <QVBoxLayout>
#include <InputMethod.h>
@@ -20,6 +25,103 @@
#include "mainwidget.h"
#include "InkJetPrinter.h"
#include "Log/filelogger.h"
#include <iostream>
#include <fstream>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <cxxabi.h>
#include <cstdlib>
#include <cstdio>
#include <execinfo.h>
QString gAppNameStr = "";//这是个全局变量,用于后续获取当前运行程序的绝对路径
// 全局变量保存基址
static uintptr_t g_base_address = 0;
// 回调函数:找到当前可执行文件的基址
static int find_base_address(struct dl_phdr_info *info, size_t size, void *data) {
// 检查是否是主程序(第一个加载的通常是主程序)
if (info->dlpi_name == nullptr || info->dlpi_name[0] == '\0') {
// 获取第一个段的加载地址(通常是基址)
g_base_address = info->dlpi_addr;
return 1; // 停止遍历
}
return 0; // 继续遍历
}
// 获取程序基址的函数
uintptr_t get_base_address() {
if (g_base_address == 0) {
dl_iterate_phdr(find_base_address, nullptr);
}
return g_base_address;
}
void createStackTraceFile(const char *fileName, const char *appName)
{
std::ofstream file(fileName);
if (!file.is_open()) {
std::cerr << "Error opening file: " << fileName << std::endl;
return;
}
void *array[100];
size_t size;
char **strings;
size = backtrace(array, 100);
if (size == 0) {
std::cerr << "No stack frames obtained" << std::endl;
return;
}
// 获取程序基址(PIE需要)
uintptr_t base_addr = get_base_address();
strings = backtrace_symbols(array, size);
file << "Stack trace info:\n";
file << "Base address: 0x" << std::hex << base_addr << std::dec << "\n\n";
for (size_t i = 0; i < size; ++i) {
file << strings[i] << std::endl;
// 计算偏移地址:实际地址 - 基址
uintptr_t addr = reinterpret_cast<uintptr_t>(array[i]);
uintptr_t offset = addr - base_addr;
char cmd[512];
// 使用偏移地址而不是实际地址
snprintf(cmd, sizeof(cmd), "addr2line -e %s 0x%lx", appName, offset);
FILE *fp = popen(cmd, "r");
if (fp) {
char line[256];
while (fgets(line, sizeof(line), fp)) {
file << " " << line; // 缩进显示更清晰
}
pclose(fp);
} else {
std::cerr << "Failed to run addr2line command" << std::endl;
}
file << std::endl;
}
free(strings);
file.close();
}
void signalHandler(int signum)
{
// 直接指定固定的路径
QString dumpFileName = "/home/plg/doc/dumpfile.txt";
QString appName = gAppNameStr;
createStackTraceFile(dumpFileName.toUtf8().data(), appName.toUtf8().data());
exit(signum);
}
//#define SYS_CN
/*
@@ -72,6 +174,12 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
gAppNameStr = QString::fromUtf8(argv[0]);
signal(SIGSEGV, signalHandler);
signal(SIGABRT, signalHandler);
signal(SIGILL, signalHandler);
signal(SIGFPE, signalHandler);
// 配置日志
QString configFileName = ":/conf/config.ini";
QSettings* logSettings = new QSettings(configFileName, QSettings::IniFormat, &a);
+8 -5
View File
@@ -281,7 +281,8 @@ void BarcodeEditor::applyCounterConfigToSysPara()
m_sysPara->para.eleEyeClearCntInSynMode = (m_sysPara->para.eleEyeClearCntInSynMode & 0xdf); // CNT2 = current
}
m_sysPara->devOp->writeFpgaCalandar(0);
if(m_sysPara->devOp)
m_sysPara->devOp->writeFpgaCalandar(0);
}
void BarcodeEditor::onBtnFormatClicked()
@@ -457,9 +458,11 @@ void BarcodeEditor::onContentChanged(QString content)
else {
if(ui->tabWidget->indexOf(m_counterEditor) == -1) {
ui->tabWidget->addTab(m_counterEditor, tr(u8"计数器"));
m_counterEditor->setViewModel(makeCounterVM(m_sysPara,
static_cast<COUNTER_TYPE>(m_vm.counterViewModel.counterType),
m_vm.counterViewModel.digitalNum));
if(m_sysPara) {
m_counterEditor->setViewModel(makeCounterVM(m_sysPara,
static_cast<COUNTER_TYPE>(m_vm.counterViewModel.counterType),
m_vm.counterViewModel.digitalNum));
}
}
m_counterEditor->setFixedSize(ui->tabBarcode->size());
}
@@ -594,4 +597,4 @@ void BarcodeEditor::on_cbBoxType_currentIndexChanged(int index)
if (index == 0) return;
m_qrcodeFormatEditor.setCodeType(ui->cbBoxType->currentText());
onQrcodeFormatConfirmed();
}
}
+4
View File
@@ -136,6 +136,10 @@ void PicScene::onFocusItemChanged(QGraphicsItem *newFocusItem, QGraphicsItem *ol
return;
}
connect(currFocusItem, &QObject::destroyed, this, [this](){
currFocusItem = nullptr;
});
QPoint pos(currFocusItem->x(), currFocusItem->y());
emit focusedItemPosChanged(pos);
+5
View File
@@ -1,5 +1,10 @@
#include "setnumdlg.h"
#include "ui_setnumdlg.h"
#include "SystemManage.h"
#include <QDebug>
#include "LogInfo.h"
SystemManage* sysMgr = nullptr;
SetNumDlg::SetNumDlg(QWidget *parent) :
QDialog(parent),
+8 -4
View File
@@ -432,7 +432,8 @@ void TestPrintWidget::saveFile(){
}
writer.writeEmptyElement("PrintSettings");
PrintSettingModel::saveToXml(m_printSetting->model(), writer);
if(m_printSetting)
PrintSettingModel::saveToXml(m_printSetting->model(), writer);
writer.writeEndElement(); // 结束根元素 </picscenes>
writer.writeEndDocument(); // 结束文档
@@ -618,8 +619,10 @@ void TestPrintWidget::parseVbfile(QXmlStreamReader &reader, bool loadPrintSettin
QXmlStreamAttributes attrs = reader.attributes();
PrintSettingModel model;
PrintSettingModel::loadFromXml(model, attrs);
m_printSetting->setModel(model);
m_printSetting->applyPrintSettingsToSysPara(false);
if(m_printSetting) {
m_printSetting->setModel(model);
m_printSetting->applyPrintSettingsToSysPara(false);
}
reader.skipCurrentElement();
}
@@ -1119,7 +1122,8 @@ void TestPrintWidget::on_newfileButton_pressed()
if (sysPara) {
PrintSettingModel defModel = PrintSettingModel::defPrintSettingModel();
PrintSettingModel::applyToSysPara(defModel, sysPara);
m_printSetting->setModel(defModel);
if(m_printSetting)
m_printSetting->setModel(defModel);
}
sendButtonClickedSignal(21); //新建文件完成