c++ - How can I fix an assertion failure that states 'vector subscript out of range'
问题描述
Other questions that I viewed before posting this question:
Debug Assertion Failed: Vector subscript out of range
Debug Assertion Failed Vector Subscript Out of Range C++
I am working on a Boids project, details of which can be found here:
https://www.red3d.com/cwr/boids/
From what I can gather my issue is something to do with an index getting accessed by the function but no data is present in the index. I had this issue yesterday in a different area of my code and fixed it by making one of my getters return a reference rather than a copy of a class object. That approach seems to not be the issue today.
Below is my code:
This code is a snippet from my function that handles simulation events. This is the code that I have narrowed down the issue to.
//Remove flocking organisms with < 0 enery storage.
for (int i = 0; i < m_flock.getSize(); i++)
{
if (m_flock.getOrganism(i).getEnergyStore() <= 0)
{
m_flock.removeOrganism(i);
//m_notFlocking.flock.erase(m_notFlocking.flock.begin() + i);
cout << "Organism died and has been removed..." << endl;
}
}
The code below is from my Flock.cpp class definition file which details information on storing boids in a vector to then apply flocking behaviors to. This class function is giving the following error:
Unhandled exception at 0x7B87FC66 (ucrtbased.dll) in EvoSim.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
Code:
Organism &Flock::getOrganism(int i)
{
return flock[i];
}
My suspicion is that the for loop size is not reflecting the recently erased object.
How can I fix the vector subscript error?
Edit:
This is the break point that shows up in the debugger:
_NODISCARD _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ {
auto& _My_data = _Mypair._Myval2;
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(
_Pos < static_cast<size_type>(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _My_data._Myfirst[_Pos];
}
Edit 2:
I did some messing around and discovered the issue only occurs when I run VS 2019 in debug mode, otherwise in Release mode it works fine and as expected.
解决方案
I see nothing in this code that can cause an out of bounds access. However, you should not increment i
on any loop iteration that removes an organism, otherwise you will skip the next organism in the list.
Imagine on the 1st loop iteration, the organism at index 0 needs to be removed. Subsequent organisms move down the list. On the next loop iteration, i
gets incremented to 1, and the organism that had moved into index 0 is skipped.
Try this instead:
//Remove flocking organisms with < 0 enery storage.
for (int i = 0; i < m_flock.getSize(); )
{
if (m_flock.getOrganism(i).getEnergyStore() <= 0)
{
m_flock.removeOrganism(i);
cout << "Organism died and has been removed..." << endl;
}
else
++i;
}
Alternatively, you can replace the entire loop using the erase-remove idiom via std::remove_if()
and std::vector::erase()
, eg:
void Flock::removeDeadOrganisms()
{
//Remove flocking organisms with < 0 enery storage.
flock.erase(
std::remove_if(flock.begin(), flock.end(),
[](const auto &o){ return o.getEnergyStore() <= 0; }
),
flock.end()
);
}
...
m_flock.removeDeadOrganisms();
Or, in C++20, via std::erase_if()
, eg:
void Flock::removeDeadOrganisms()
{
//Remove flocking organisms with < 0 enery storage.
std::erase_if(flock,
[](const auto &o){ return o.getEnergyStore() <= 0; }
);
}
推荐阅读
- c# - Nuget 包中的 PrecompiledView 未进入应用程序
- c - 生产者-消费者程序:我应该在临界区内部还是外部更改信号量的值?
- html - html5
- javascript - 如何将 javascript 字符串传递给 javascript,然后将输出转换为字符串以传递给函数
- azure - Azure Databricks Notebook 未传递参数
- javascript - 如果我第一次打开模态框,我的第二个模态框的关闭按钮不起作用。但它只有在我打开和关闭我的第三个模式后才有效?
- python - 仅对 DatetimeIndex、TimedeltaIndex 或 PeriodIndex 有效,但有一个“Index”实例
- flutter - 可从顶部和底部拖动的可滚动工作表
- javascript - 从两个对象数组追加属性
- html - 如果每个导航元素有元素,则为每个导航元素添加 + 和 - 图标