4.4 KiB
4.4 KiB
段错误修复说明
问题定位
段错误发生在 ECG_12LEAD_Data_Mapper 函数的这一行:
output_channels[9][sample] = -0.5f * (lead_I + lead_II); // aVR
根本原因
1. 数组未初始化
// 问题代码:只创建了向量,但没有设置大小
std::vector<std::vector<float>> output_channels(12);
// 此时 output_channels[9] 是一个空的向量,访问 [sample] 会导致段错误
2. 缺少边界检查
// 问题代码:直接访问数组元素,没有验证索引和大小
output_channels[9][sample] = value; // 可能越界
修复方案
1. 正确初始化所有通道
// 修复后:为所有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. 添加边界检查
// 修复后:在访问数组前验证索引和大小
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. 验证输入数据一致性
// 修复后:确保所有前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. 验证输出数据完整性
// 修复后:确保所有输出通道都有正确的大小
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));
}
}
修复前后的对比
修复前(有段错误风险)
// 创建12导联输出结构
std::vector<std::vector<float>> output_channels(12);
// 直接访问未初始化的通道
output_channels[9][sample] = value; // ❌ 段错误!
修复后(安全)
// 创建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. 始终初始化容器
// 好的做法
std::vector<std::vector<float>> channels(12);
for (auto& ch : channels) {
ch.resize(expected_size, default_value);
}
2. 使用范围检查
// 好的做法
if (index < container.size() && sample < container[index].size()) {
container[index][sample] = value;
}
3. 添加调试信息
// 好的做法
std::cout << "Creating " << num_channels << " channels with " << num_samples << " samples each" << std::endl;
测试建议
- 运行测试模式1: 验证解析器工作正常
- 运行测试模式2: 测试完整的映射流程
- 观察调试输出: 确认所有通道都被正确初始化
- 检查输出文件: 验证12导联数据完整性
现在段错误应该已经被修复,程序可以安全地处理12导联心电数据了!