So i'm getting a Segmentation fault: 11 error and I know which block is causing it, but i'm trying to understand why.
std::vector<Entity> grassEntities;
for (int i = 0; i < 40; i ) {
grassEntities.push_back(Entity(i * 32, 592, grassTexture));
}
std::vector<Entity> dirtEntities;
for (int i = 0; i < 4; i ) {
for (int j = 0; j < 41; j ) {
dirtEntities.push_back(Entity(j * 32, (688 - (i * 32)), dirtTexture));
}
}
bool gameRunning = true;
SDL_Event event;
while (gameRunning) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
gameRunning = false;
}
window.clear();
std::vector<Entity>::iterator it;
std::vector<Entity>::iterator it2;
for (it = dirtEntities.end(); it >= dirtEntities.begin(); it--){
window.render(*it);
}
for (it2 = grassEntities.end(); it2 >= grassEntities.begin(); it2--){
window.render(*it2);
}
window.display();
}
this issue lies with this section
for (it2 = grassEntities.end(); it2 >= grassEntities.begin(); it2--){
window.render(*it2);
}
which for me is odd because this section seemed to work just fine:
for (it = dirtEntities.end(); it >= dirtEntities.begin(); it--){
window.render(*it);
}
CodePudding user response:
Inside the game loop, in the first iteration of both for
loops, it
is equal to dirtEntities.end()
and it2
is equal to grassEntities.end()
. Dereferencing end
iterators is undefined behaviour. The fact that the code doesn't crash is just "lucky".
If you want to iterate in reverse, use reverse iterators instead:
for (auto it = dirtEntities.rbegin(); it != dirtEntities.rend(); it ){
window.render(*it);
}
for (auto it2 = grassEntities.rbegin(); it2 != grassEntities.rend(); it2 ){
window.render(*it2);
}
CodePudding user response:
The iterator returned by .end()
is not defererencable. The loop should be rewritten as
for (auto it = dirtEntities.end(); it != dirtEntities.begin();)
{
--it;
// ...
}
Learn how to enable iterator debugging in your compiler. Those kind of errors can be detected automatically.
CodePudding user response:
The end() method from vector returns an iterator referring to the past-the-end element in the container.
It is not the best practice to read the value from this iterator.
If you want to read the value of the last element you should use reverse_iterator instead.
std::vector<int>::reverse_iterator rit = myvector.rbegin();
rbegin() returns you the iterator to the last element inside the container.
CodePudding user response:
for me is odd because this section works just fine:
No, the program has undefined behavior meaning it is still in error even if it doesn't say so explicitly and "seems to be working". This is because for the very first iteration you're dereferencing it
which is the iterator returned by the call to end
.
//------------vvv---->undefined behavior for the first iteration
window.render(*it);
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
1For a more technically accurate definition of undefined behavior see this, where it is mentioned that: there are no restrictions on the behavior of the program.