C++代码运行触发libc++abi终止错误,求修复getCasesOverTime函数
修复C++中std::length_error异常及getCasesOverTime函数逻辑问题
问题重现
代码编译通过,但运行时抛出异常:
libc++abi: terminating with uncaught exception of type std::length_error: vector zsh: abort
核心功能是CovidCaseMap::getCasesOverTime函数,用于返回随时间变化的活跃病例数据,但存在内存越界和逻辑错误。
错误原因分析
- 返回局部容器的引用:
getCasesOverTime返回vector<TimeAndCaseData> &,但函数内的data是局部变量,函数执行结束后会被销毁,返回的引用变成悬空引用,后续访问会触发未定义行为,可能引发std::length_error或其他内存异常。 - 数组越界访问:循环条件
j < caseTime.size()*2+1会导致caseTime[j]的访问超出vector范围。比如测试用例中caseTime有5个元素,索引最大为4,但循环会走到j=10,此时caseTime[j]访问的是不存在的内存,触发越界错误。 - 逻辑错误:原循环逻辑无法正确处理病例的开始和结束事件,没有收集所有关键时间点(每个病例的开始时间和结束时间),导致生成的时间点序列不符合预期。
修复后的代码
修改后的CovidCaseMap.h
#ifndef COVIDCASEMAP_H #define COVIDCASEMAP_H #include "CovidCase.h" #include <vector> #include <algorithm> // 加入sort所需头文件 //Record the number of active cases from some point in time class TimeAndCaseData { private: int time; int currentCases; public: //constructor TimeAndCaseData(const int timeIn, const int currentCasesIn) : time(timeIn), currentCases(currentCasesIn) // 使用成员初始化列表更规范 {} // 修改为const成员函数,避免外部修改内部数据 int getTime() const { return time; } int getNumberOfCases() const { return currentCases; } }; class CovidCaseMap { private: std::vector<CovidCase> covidCases; public: void addCase(const CovidCase & c) { covidCases.push_back(c); } // 改为返回值,而非引用,避免悬空引用 std::vector<TimeAndCaseData> getCasesOverTime(int activeHours) { std::vector<TimeAndCaseData> data; // 存储事件:pair<时间, 病例变化量(+1或-1)> std::vector<std::pair<int, int>> events; // 收集所有病例的开始和结束事件 for(const auto& caseObj : covidCases) { int startTime = caseObj.getTime(); events.emplace_back(startTime, 1); // 开始事件:病例+1 events.emplace_back(startTime + activeHours, -1); // 结束事件:病例-1 } // 排序事件:先按时间升序,时间相同时,结束事件(-1)优先于开始事件(+1) std::sort(events.begin(), events.end(), [](const auto& a, const auto& b) { if(a.first != b.first) return a.first < b.first; // 时间相同时,先处理减病例的事件,避免同一时间点病例数错误波动 return a.second < b.second; }); // 初始化初始状态 int currentCases = 0; data.emplace_back(0, currentCases); // 遍历事件生成时间序列 int prevTime = 0; for(const auto& event : events) { int eventTime = event.first; int change = event.second; // 如果当前事件时间和上一个记录时间不同,才添加新记录 if(eventTime != prevTime) { data.emplace_back(eventTime, currentCases); prevTime = eventTime; } // 更新当前病例数 currentCases += change; // 添加病例数变化后的记录 data.emplace_back(eventTime, currentCases); } // 去重:移除连续相同的时间点(可选,根据需求调整) auto last = std::unique(data.begin(), data.end(), [](const auto& a, const auto& b) { return a.getTime() == b.getTime() && a.getNumberOfCases() == b.getNumberOfCases(); }); data.erase(last, data.end()); return data; } }; #endif // COVIDCASEMAP_H
测试代码说明
测试代码无需修改,因为修改后的getTime和getNumberOfCases为const成员函数,仅用于读取值,不影响测试逻辑的执行。
修复点说明
- 返回值修改:将
vector<TimeAndCaseData> &改为vector<TimeAndCaseData>,返回局部容器的副本(C++11及以上会自动优化为移动操作,性能无影响),彻底解决悬空引用问题。 - 事件驱动逻辑重构:
- 收集每个病例的开始(+1)和结束(-1)事件,确保所有关键时间点都被覆盖。
- 对事件排序,处理时间相同的事件优先级,避免同一时间点病例数计算错误。
- 遍历事件时维护当前活跃病例数,生成正确的时间-病例数序列。
- 成员函数const修正:将
getTime和getNumberOfCases改为const成员函数,禁止外部修改内部数据,提升代码安全性。 - 添加必要头文件:加入
<algorithm>头文件,确保sort和unique函数能正常编译。
内容的提问来源于stack exchange,提问作者King's Dev
相关产品推荐
相关产品推荐

