I’ve written a long and complicated server program on windows. Used visual studio 2019.
Then I’ve created a CentOS 8 operating system on vm virtualbox and transferred all the code there. And rebuilt an executable with visual code. That works okay except one part.
Here is the code that causes the crash:
//clients is std::map<int, boost::shared_ptr<Client>> clients;
for (const auto& kv : clients) {
int elapsed_seconds = boost::chrono::duration_cast<boost::chrono::seconds>(timeNow - kv.second->lastUpdated).count();
int i = kv.first;
if (elapsed_seconds >= ServerData::SessionTimeoutSeconds)
{
trash_bin.push_back(clients[i]);
clients.erase(i);
}
}
this works without any bug on windows(compiled with visual studio 2019)
but gives this error on centos 8 (compiled with visual code / g++)
Assertion `px != 0′ failed. Aborted (core dumped)
But if I put break; right after client.erase(i); problem is solved.
if (elapsed_seconds >= ServerData::SessionTimeoutSeconds)
{
trash_bin.push_back(clients[i]);
clients.erase(i);
break;//this line makes it work.
}
So problem is caused when for loop iterates after deleting something from clients.
The question is :
Why does it solve this problem automatically, without breaking out of the loop on the code compiled on windows but cannot solve it on centos 8 ?
3
Answers
This iterates over the range using iterators. After the loop body is executed each time, the iterator is incremented.
This invalidates the current iterator. When the invalid iterator is incremented after the loop body, the behaviour of the program is undefined.
Because when you break out of the loop before the invalid iterator is incremented, there is no undefined behaviour.
I agree with @eerorika. Also, your
break
statement breaks out of the loop. Without it, the loop continues executing after yourif
statement gets atrue
condition. That’s a very different action. Is your loop intended to delete only one client at a time?Unless you only want to erase the first timed-out client, instead of all timed-out clients (which is more likely), then there is a bug in your code.
Is this what you intended?: