You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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函数,用于返回随时间变化的活跃病例数据,但存在内存越界和逻辑错误。

错误原因分析

  1. 返回局部容器的引用:getCasesOverTime返回vector<TimeAndCaseData> &,但函数内的data是局部变量,函数执行结束后会被销毁,返回的引用变成悬空引用,后续访问会触发未定义行为,可能引发std::length_error或其他内存异常。
  2. 数组越界访问:循环条件j < caseTime.size()*2+1会导致caseTime[j]的访问超出vector范围。比如测试用例中caseTime有5个元素,索引最大为4,但循环会走到j=10,此时caseTime[j]访问的是不存在的内存,触发越界错误。
  3. 逻辑错误:原循环逻辑无法正确处理病例的开始和结束事件,没有收集所有关键时间点(每个病例的开始时间和结束时间),导致生成的时间点序列不符合预期。

修复后的代码

修改后的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成员函数,仅用于读取值,不影响测试逻辑的执行。

修复点说明

  1. 返回值修改:将vector<TimeAndCaseData> &改为vector<TimeAndCaseData>,返回局部容器的副本(C++11及以上会自动优化为移动操作,性能无影响),彻底解决悬空引用问题。
  2. 事件驱动逻辑重构:
    • 收集每个病例的开始(+1)和结束(-1)事件,确保所有关键时间点都被覆盖。
    • 对事件排序,处理时间相同的事件优先级,避免同一时间点病例数计算错误。
    • 遍历事件时维护当前活跃病例数,生成正确的时间-病例数序列。
  3. 成员函数const修正:将getTime和getNumberOfCases改为const成员函数,禁止外部修改内部数据,提升代码安全性。
  4. 添加必要头文件:加入<algorithm>头文件,确保sort和unique函数能正常编译。

内容的提问来源于stack exchange,提问作者King's Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:10:47