medical_SDK/SEGMENTATION_FAULT_FIX.md

145 lines
4.4 KiB
Markdown
Raw Normal View History

2025-08-25 10:53:22 +08:00
# 段错误修复说明
## 问题定位
段错误发生在 `ECG_12LEAD_Data_Mapper` 函数的这一行:
```cpp
output_channels[9][sample] = -0.5f * (lead_I + lead_II); // aVR
```
## 根本原因
### 1. **数组未初始化**
```cpp
// 问题代码:只创建了向量,但没有设置大小
std::vector<std::vector<float>> output_channels(12);
// 此时 output_channels[9] 是一个空的向量,访问 [sample] 会导致段错误
```
### 2. **缺少边界检查**
```cpp
// 问题代码:直接访问数组元素,没有验证索引和大小
output_channels[9][sample] = value; // 可能越界
```
## 修复方案
### 1. **正确初始化所有通道**
```cpp
// 修复后为所有12个通道设置正确的大小
std::vector<std::vector<float>> output_channels(12);
for (int ch = 0; ch < 12; ++ch) {
output_channels[ch].resize(num_samples, 0.0f); // 初始化为0
}
```
### 2. **添加边界检查**
```cpp
// 修复后:在访问数组前验证索引和大小
if (9 < output_channels.size() && 10 < output_channels.size() && 11 < output_channels.size()) {
if (sample < output_channels[9].size() && sample < output_channels[10].size() && sample < output_channels[11].size()) {
output_channels[9][sample] = -0.5f * (lead_I + lead_II); // aVR
output_channels[10][sample] = lead_I - 0.5f * lead_II; // aVL
output_channels[11][sample] = lead_II - 0.5f * lead_I; // aVF
}
}
```
### 3. **验证输入数据一致性**
```cpp
// 修复后确保所有前8个通道都有相同的采样点数
for (size_t i = 1; i < 8; ++i) {
if (input_channels[i].size() != num_samples) {
throw std::runtime_error("Channel " + std::to_string(i) + " has different sample count: " +
std::to_string(input_channels[i].size()) + " vs " + std::to_string(num_samples));
}
}
```
### 4. **验证输出数据完整性**
```cpp
// 修复后:确保所有输出通道都有正确的大小
for (size_t ch = 0; ch < output_channels.size(); ++ch) {
if (output_channels[ch].size() != num_samples) {
throw std::runtime_error("Output channel " + std::to_string(ch) + " has incorrect size: " +
std::to_string(output_channels[ch].size()) + " vs expected " + std::to_string(num_samples));
}
}
```
## 修复前后的对比
### **修复前(有段错误风险)**
```cpp
// 创建12导联输出结构
std::vector<std::vector<float>> output_channels(12);
// 直接访问未初始化的通道
output_channels[9][sample] = value; // ❌ 段错误!
```
### **修复后(安全)**
```cpp
// 创建12导联输出结构并初始化所有通道的大小
std::vector<std::vector<float>> output_channels(12);
for (int ch = 0; ch < 12; ++ch) {
output_channels[ch].resize(num_samples, 0.0f); // 初始化为0
}
// 安全的数组访问
if (9 < output_channels.size() && sample < output_channels[9].size()) {
output_channels[9][sample] = value; // ✅ 安全
}
```
## 技术要点
### 1. **向量初始化的重要性**
- `std::vector<std::vector<float>>(12)` 只创建了12个空的向量
- 每个内部向量需要单独调用 `resize()` 设置大小
- 使用 `resize(size, default_value)` 可以同时设置大小和默认值
### 2. **边界检查的必要性**
- 即使理论上索引应该有效,也要进行边界检查
- 使用 `if` 语句验证索引和大小
- 提供清晰的错误信息,便于调试
### 3. **数据一致性验证**
- 确保所有输入通道有相同的采样点数
- 验证输出通道的完整性
- 在关键步骤添加断言或异常
## 预防措施
### 1. **始终初始化容器**
```cpp
// 好的做法
std::vector<std::vector<float>> channels(12);
for (auto& ch : channels) {
ch.resize(expected_size, default_value);
}
```
### 2. **使用范围检查**
```cpp
// 好的做法
if (index < container.size() && sample < container[index].size()) {
container[index][sample] = value;
}
```
### 3. **添加调试信息**
```cpp
// 好的做法
std::cout << "Creating " << num_channels << " channels with " << num_samples << " samples each" << std::endl;
```
## 测试建议
1. **运行测试模式1**: 验证解析器工作正常
2. **运行测试模式2**: 测试完整的映射流程
3. **观察调试输出**: 确认所有通道都被正确初始化
4. **检查输出文件**: 验证12导联数据完整性
现在段错误应该已经被修复程序可以安全地处理12导联心电数据了