# DroneScrewServer 崩溃问题修复总结 ## 问题描述 程序在运行约 20 分钟后崩溃(退出码 255),日志显示: - 处理了约 2100 帧图像后突然退出 - 没有任何错误日志,表明发生了未捕获的异常或段错误 - 最后日志:`right frame #2100` → 直接崩溃 ## 根本原因分析 从代码审查发现以下风险点: ### 1. **相机回调函数缺少异常保护**(最可能的原因) - `leftCameraCallback` 和 `rightCameraCallback` 在相机 SDK 线程中被调用 - 包含内存分配、拷贝、RTSP 推流等操作,但没有 try-catch - 任何异常都会导致程序崩溃 ### 2. **心跳日志内存信息不完整** - `procStatusValue("VmRSS")` 返回空字符串 - 无法监控内存增长情况 ### 3. **算法库调用缺少保护** - `m_pAlgo->Detect()` 可能抛出异常 - 第三方算法库崩溃会导致整个进程退出 ### 4. **GPIO 触发线程缺少异常保护** - 长时间运行的线程没有顶层异常捕获 ## 修复方案 ### 1. 相机回调异常保护(关键修复) **文件**: `DroneScrewServerPresenter.cpp` #### `leftCameraCallback` 函数 - 整个函数体包裹在 `try-catch` 中 - 捕获 `std::bad_alloc`、`std::exception` 和未知异常 - 增加内存重新分配的日志(realloc log) ```cpp void DroneScrewServerPresenter::leftCameraCallback(const MvsImageData& img) { try { // ... 原有逻辑 ... } catch (const std::bad_alloc& e) { LOG_ERROR("[CAM] left callback bad_alloc frame=%llu size=%zu: %s\n", ...); } catch (const std::exception& e) { LOG_ERROR("[CAM] left callback exception frame=%llu: %s\n", ...); } catch (...) { LOG_ERROR("[CAM] left callback unknown exception frame=%llu\n", ...); } } ``` #### `rightCameraCallback` 函数 - 同样增加异常保护 - 增加内存重新分配的日志 ### 2. 算法调用异常保护 **文件**: `DroneScrewServerPresenter.cpp` → `detectThreadFunc()` ```cpp if (m_pAlgo) { try { m_pAlgo->Detect(inLeft, inRight, result); } catch (const std::exception& e) { LOG_ERROR("[DETECT] algo exception frame=%llu: %s\n", ...); result.success = false; result.errorCode = -1; result.message = std::string("Algorithm exception: ") + e.what(); } catch (...) { LOG_ERROR("[DETECT] algo unknown exception frame=%llu\n", ...); // ... 设置错误状态 ... } } ``` ### 3. GPIO 触发线程异常保护 **文件**: `DroneScrewServerPresenter.cpp` → `triggerThreadFunc()` - 整个 while 循环包裹在 try-catch 中 - 防止 GPIO 操作异常导致程序崩溃 ### 4. 增强心跳日志 **文件**: `main.cpp` ```cpp const QString rss = procStatusValue("VmRSS"); const QString vmPeak = procStatusValue("VmPeak"); const QString vmSize = procStatusValue("VmSize"); const QString threads = procStatusValue("Threads"); LOG_INFO("[HEARTBEAT] uptime=%llds mode=%s rss=%s vmPeak=%s vmSize=%s threads=%s\n", ..., rss.isEmpty() ? "N/A" : rss.toStdString().c_str(), ...); ``` 增加的字段: - `vmPeak`: 峰值虚拟内存 - `vmSize`: 当前虚拟内存 - 空值显示为 "N/A" 而非空字符串 ## 诊断日志增强 ### 相机回调 - 内存重新分配时打印旧/新 size - 异常时记录帧 ID、数据大小和异常信息 ### 心跳监控 - 显示内存使用趋势(RSS、VmPeak、VmSize) - 线程数量监控 ### 算法调用 - 异常时记录帧 ID 和错误信息 - 将错误信息传递给结果对象 ## 测试建议 1. **长时运行测试** - 运行 30 分钟以上,观察是否还会崩溃 - 监控心跳日志中的内存变化 2. **关键日志观察** ```bash # 监控异常日志 grep -E "exception|unknown exception|bad_alloc" log.log # 监控内存增长 grep "HEARTBEAT" log.log # 监控内存重新分配 grep "realloc" log.log ``` 3. **预期结果** - 如果是相机回调异常:会看到 `[CAM] left/right callback exception` 但程序不崩溃 - 如果是算法异常:会看到 `[DETECT] algo exception` 但程序继续运行 - 如果是内存泄漏:心跳日志会显示内存持续增长 - 如果是 GPIO 异常:会看到 `[GPIO] trigger thread exception` 但程序不崩溃 ## 下一步行动 1. **编译并部署**修改后的代码 2. **运行至少 30 分钟**,观察日志 3. **记录所有异常日志**,分析根本原因 4. **根据日志反馈**进行针对性修复 ## 注意事项 - 所有异常捕获都会记录日志,不会静默失败 - 异常保护只是防止崩溃,并不解决根本问题 - 看到异常日志后需要进一步分析根本原因 - 如果频繁出现异常,说明存在更深层的问题需要修复 ## 修改文件清单 1. `App/DroneScrewbolt/DroneScrewServer/DroneScrewServerPresenter.cpp` - `leftCameraCallback()` - 增加异常保护和内存重分配日志 - `rightCameraCallback()` - 增加异常保护和内存重分配日志 - `detectThreadFunc()` - 算法调用增加异常保护 - `triggerThreadFunc()` - 增加异常保护 2. `App/DroneScrewbolt/DroneScrewServer/main.cpp` - 心跳日志增强:增加 vmPeak、vmSize 字段 - 处理空值显示为 "N/A"