在std: vector中擦除,调试,释放
erase in std::vector, debug, release
std::vector<int> va;
//和push_back 1~100
std::vector<int>::iterator i = va.begin();
for(i; i != va.end(); )
{
if((*i) == 5) va.erase(i);
else i++
}
这个代码在调试运行时100%崩溃。
但是不要在发布运行时使此代码崩溃。
为什么会这样?
这段代码中的调试和发布模式有什么不同?
您有未定义的行为,因为您正在使用无效的迭代器(i
被erase()
无效)。
通过使用Erase-remove习语来避免整个问题:
va.erase(std::remove(va.begin(), va.end(), 5), va.end());
正如其他人指出的那样,崩溃是由于调用va.erase()
后继续使用的无效迭代器造成的。
现在,至于为什么它在Release模式下工作,在某些情况下,Release模式下std::vector<>
的迭代器是一个指向动态分配数组的简单指针。当调用erase时,迭代器继续指向数组的相同元素,而数组的内容已经被erase
函数移动。这是未定义的行为,特定于标准库实现,但非常常见。在任何情况下都不应该依赖可移植代码中的行为
然而,在一些标准库实现中,调试模式迭代器执行检查,并且比简单指针更复杂。因此,它们可以检测到您正在做一些不合法的事情并故意导致崩溃,因此您可以认识到自己的错误。
vector::erase
返回一个新的迭代器,因为它使当前的迭代器无效。
if((*i) == 5) va.erase(i);
应该if((*i) == 5) i = va.erase(i);
相关文章:
- 当回溯以零开始时,如何调试崩溃
- 释放错误后堆使用
- G锁定铸造到基础上会释放模拟行为
- 在将变量声明为引用时,堆在释放后使用
- 在linux上调试巨大的C++项目
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- MS Visual C 释放和调试构建之间的不同行为的可能原因
- ActiveX OCX可以在释放模式内置时注册,但不能在调试模式下注册
- 断言在释放中抛出,但不进行调试 - 一定是编译器错误
- 如何在程序崩溃后释放managedsharedmemory:在调试过程中使用哪些有效的技术
- 使用 Valgrind 调试释放后使用
- C 可能不确定的行为会导致调试和释放构建行为不同
- 调试对释放内存的非法访问
- 调试断言失败!错误的内存释放
- 在调试模式下释放静态数组时出错
- 进行内存释放时出现调试错误
- 在std: vector中擦除,调试,释放
- 串口工作在调试,但不释放c++代码块窗口
- 调试DLL与释放EXE