medical_SDK/log/SEGMENTATION_FAULT_FIX.md

145 lines
4.4 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.

# 段错误修复说明
## 问题定位
段错误发生在 `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导联心电数据了