cpp容器迭代器使用导致程序崩溃

⌚Time: 2024-09-14 10:06:00

👨‍💻Author: Jack Ge

昨天我遇到问题,程序崩溃。第一个提示容器迭代器不可引用,第二个提示库超出范围

绿色史莱姆在释放蓝色史莱姆后崩溃。从调用堆栈里面发现是精灵管理器的update函数里,调用精灵的update函数更新后就崩溃了。之后在更新前后打印精灵的名字,一开始怀疑是释放的蓝色史莱姆问题,结果发现是绿色史莱姆更新后崩溃

void update(){
    ...
    for (auto sprite = vec.begin();sprite != vec.end();){
        (*sprite)->update();
        //在这里崩溃
        if((*sprite)->is_sprite_alive()){
            sprite++;
        }else{
            //删除精灵
            //...
            sprite = vec.erase(sprite);
        }
    }
}

在断点发现精灵迭代器指向的位置已经不可用了。我怀疑是不是销毁了什么东西。我就定位到精灵类的update函数,在绿色史莱姆更新时打印一些信息。确认在哪里开始崩溃的。结果发现整个绿色史莱姆的update函数运行完了也没有崩溃。而跳出这个函数回到了精灵管理器,再使用这个精灵就会崩溃。

所以我就陷入疑惑。在函数执行时没有问题和崩溃,之后就崩溃了。

后来我就关闭了电脑看了一会周淑怡的直播,准备睡觉。之后想出了原因,迭代器失效。在绿色精灵的update函数里会更新技能,而技能会创建蓝色史莱姆,创建后导致精灵容器内容增加,迭代器失效。

第二天尝试这个原因,把迭代器遍历改成索引遍历,果然就不崩溃了。

for(unsigned int i=0; i<vec.size(); ){
    vec.at(i)->update();
    if(vec.at(i)->is_sprite_alive()){
        i++;
    }else{
        //销毁精灵
        ...
        vec.erase(vec.begin()+i);
    }
}

问AI说删除元素会让迭代器失效,增加元素不会元素改变顺序,不会导致迭代器失效。但是不知道为什么我这里确实失效了。我也不想知道了。反正已经解决了。


总结

一般程序崩溃无非就是使用了使用了空指针,没有实例化指针,指针地址被改变和不可用,操作销毁后的实例,总之就是指针,迭代器,访问越界的问题。是设计的缺陷。