重复执行pop_back()与push_back()引发Segmentation fault原因求解
问题根因分析
你的代码触发了C++标准定义的未定义行为(UB):std::vector的pop_back()成员函数有前置要求——调用时容器必须非空,空容器执行pop_back()的行为没有任何标准约束,段错误是这类未定义行为的典型表现之一。
我们可以明确原代码的执行逻辑:
- 初始状态下
test是空容器 - 第一次循环
i=0,满足i % 2 == 0,执行push_back(0),容器大小变为1 - 紧接着执行
pop_back(),容器回到空状态 - 第二次循环
i=1,不满足if条件,不会执行push_back,容器保持空 - 直接执行
pop_back(),此时为空容器调用pop_back,触发未定义行为,表现为段错误。
各修改操作消除错误的原理
- 删除if语句:每次循环都会先执行push_back让容器大小+1,再执行pop_back让大小-1,容器永远不会为空,不会触发空pop的未定义行为,自然不会出现段错误。
- 在pop_back前添加else关键字:此时逻辑变为
if(i%2==0) push_back(i); else pop_back();,执行流为:i=0push(大小1)→i=1pop(大小0)→i=2push(大小1)→i=3pop(大小0),永远是push和pop交替执行,不会出现空容器时调用pop_back的情况,不会触发未定义行为。 - 单独移除push_back操作:未定义行为不代表必然崩溃,其表现完全由编译器实现、编译参数、运行环境决定。当你移除push_back后,第一次循环就会触发空pop的未定义行为,但部分编译器的
std::vector实现中,空pop_back不会直接访问非法内存,只是对内部size计数做减法,不会触发段错误;如果你在循环前预先push了若干元素,只要pop的总次数不超过预先push的元素数量,容器就不会变空,自然也不会出现问题。 - 单独移除pop_back操作:全程只有push_back操作,容器持续扩容,永远不会出现空容器调用pop_back的场景,不会触发错误。
补充说明:你观察到“移除push_back后哪怕预先push若干元素也不会出问题”,本质是如果预先push的元素数量≥循环次数,容器全程不会为空,自然不会触发未定义行为;如果预先push的数量小于10000,依然会触发空pop的未定义行为,只是不一定表现为段错误而已,这正是未定义行为的典型特征:没有固定的错误表现,可能崩溃、可能正常运行、也可能输出异常结果。
内容的提问来源于stack exchange,提问作者Vagente King
相关产品推荐
相关产品推荐

