strange segmentation fault during function return - c++

I am running a program on 2 different machines. On one it works fine without issue. On the other it results in a segmentation fault. Through debugging, I have figured out where the fault occurs, but I can't figure out a logical reason for it to happen.
In one function I have the following code:
pass_particles(particle_grid, particle_properties, input_data, coll_eros_track, collision_number_part, world, grid_rank_lookup, grid_locations);
cout<<"done passing particles"<<endl;
The function pass_particles looks like:
void pass_particles(map<int,map<int,Particle> > & particle_grid, std::vector<Particle_props> & particle_properties, User_input& input_data, data_tracking & coll_eros_track, vector<int> & collision_number_part, mpi::communicator & world, std::map<int,int> & grid_rank_lookup, map<int,std::vector<double> > & grid_locations)
{
//cout<<"east-west"<<endl;
//east-west exchange (x direction)
map<int, vector<Particle> > particles_to_be_sent_east;
map<int, vector<Particle> > particles_to_be_sent_west;
vector<Particle> particles_received_east;
vector<Particle> particles_received_west;
int counter_x_sent=0;
int counter_x_received=0;
for(grid_iter=particle_grid.begin();grid_iter!=particle_grid.end();grid_iter++)
{
map<int,Particle>::iterator part_iter;
for (part_iter=grid_iter->second.begin();part_iter!=grid_iter->second.end();)
{
if (particle_properties[part_iter->second.global_part_num()].particle_in_box()[grid_iter->first])
{
//decide if a particle has left the box...need to consider whether particle was already outside the box
if ((part_iter->second.position().x()<(grid_locations[grid_iter->first][0]) && part_iter->second.position().x()>(grid_locations[grid_iter->first-input_data.z_numboxes()][0]))
|| (input_data.periodic_walls_x() && (grid_iter->first-floor(grid_iter->first/(input_data.xz_numboxes()))*input_data.xz_numboxes()<input_data.z_numboxes()) && (part_iter->second.position().x()>(grid_locations[input_data.total_boxes()-1][0]))))
{
particles_to_be_sent_west[grid_iter->first].push_back(part_iter->second);
particle_properties[particle_grid[grid_iter->first][part_iter->first].global_part_num()].particle_in_box()[grid_iter->first]=false;
counter_sent++;
counter_x_sent++;
}
else if ((part_iter->second.position().x()>(grid_locations[grid_iter->first][1]) && part_iter->second.position().x()<(grid_locations[grid_iter->first+input_data.z_numboxes()][1]))
|| (input_data.periodic_walls_x() && (grid_iter->first-floor(grid_iter->first/(input_data.xz_numboxes()))*input_data.xz_numboxes())>input_data.xz_numboxes()-input_data.z_numboxes()-1) && (part_iter->second.position().x()<(grid_locations[0][1])))
{
particles_to_be_sent_east[grid_iter->first].push_back(part_iter->second);
particle_properties[particle_grid[grid_iter->first][part_iter->first].global_part_num()].particle_in_box()[grid_iter->first]=false;
counter_sent++;
counter_x_sent++;
}
//select particles in overlap areas to send to neighboring cells
else if ((part_iter->second.position().x()>(grid_locations[grid_iter->first][0]) && part_iter->second.position().x()<(grid_locations[grid_iter->first][0]+input_data.diam_large())))
{
particles_to_be_sent_west[grid_iter->first].push_back(part_iter->second);
counter_sent++;
counter_x_sent++;
}
else if ((part_iter->second.position().x()<(grid_locations[grid_iter->first][1]) && part_iter->second.position().x()>(grid_locations[grid_iter->first][1]-input_data.diam_large())))
{
particles_to_be_sent_east[grid_iter->first].push_back(part_iter->second);
counter_sent++;
counter_x_sent++;
}
++part_iter;
}
else if (particles_received_current[grid_iter->first].find(part_iter->first)!=particles_received_current[grid_iter->first].end())
{
if ((part_iter->second.position().x()>(grid_locations[grid_iter->first][0]) && part_iter->second.position().x()<(grid_locations[grid_iter->first][0]+input_data.diam_large())))
{
particles_to_be_sent_west[grid_iter->first].push_back(part_iter->second);
counter_sent++;
counter_x_sent++;
}
else if ((part_iter->second.position().x()<(grid_locations[grid_iter->first][1]) && part_iter->second.position().x()>(grid_locations[grid_iter->first][1]-input_data.diam_large())))
{
particles_to_be_sent_east[grid_iter->first].push_back(part_iter->second);
counter_sent++;
counter_x_sent++;
}
part_iter++;
}
else
{
particle_grid[grid_iter->first].erase(part_iter++);
counter_removed++;
}
}
}
world.barrier();
mpi::request reqs_x_send[particles_to_be_sent_west.size()+particles_to_be_sent_east.size()];
vector<multimap<int,int> > box_sent_x_info;
box_sent_x_info.resize(world.size());
vector<multimap<int,int> > box_received_x_info;
box_received_x_info.resize(world.size());
int counter_x_reqs=0;
//send particles
for(grid_iter_vec=particles_to_be_sent_west.begin();grid_iter_vec!=particles_to_be_sent_west.end();grid_iter_vec++)
{
if (grid_iter_vec->second.size()!=0)
{
//send a particle. 50 will be "west" tag
if (input_data.periodic_walls_x() && (grid_iter_vec->first-floor(grid_iter_vec->first/(input_data.xz_numboxes()))*input_data.xz_numboxes()<input_data.z_numboxes()))
{
reqs_x_send[counter_x_reqs++]=world.isend(grid_rank_lookup[grid_iter_vec->first + input_data.z_numboxes()*(input_data.x_numboxes()-1)], grid_iter_vec->first + input_data.z_numboxes()*(input_data.x_numboxes()-1), particles_to_be_sent_west[grid_iter_vec->first]);
box_sent_x_info[grid_rank_lookup[grid_iter_vec->first + input_data.z_numboxes()*(input_data.x_numboxes()-1)]].insert(pair<int,int>(world.rank(), grid_iter_vec->first + input_data.z_numboxes()*(input_data.x_numboxes()-1)));
}
else if (!(grid_iter_vec->first-floor(grid_iter_vec->first/(input_data.xz_numboxes()))*input_data.xz_numboxes()<input_data.z_numboxes()))
{
reqs_x_send[counter_x_reqs++]=world.isend(grid_rank_lookup[grid_iter_vec->first - input_data.z_numboxes()], grid_iter_vec->first - input_data.z_numboxes(), particles_to_be_sent_west[grid_iter_vec->first]);
box_sent_x_info[grid_rank_lookup[grid_iter_vec->first - input_data.z_numboxes()]].insert(pair<int,int>(world.rank(),grid_iter_vec->first - input_data.z_numboxes()));
}
}
}
for(grid_iter_vec=particles_to_be_sent_east.begin();grid_iter_vec!=particles_to_be_sent_east.end();grid_iter_vec++)
{
if (grid_iter_vec->second.size()!=0)
{
//send a particle. 60 will be "east" tag
if (input_data.periodic_walls_x() && (grid_iter_vec->first-floor(grid_iter_vec->first/(input_data.xz_numboxes())*input_data.xz_numboxes())>input_data.xz_numboxes()-input_data.z_numboxes()-1))
{
reqs_x_send[counter_x_reqs++]=world.isend(grid_rank_lookup[grid_iter_vec->first - input_data.z_numboxes()*(input_data.x_numboxes()-1)], 2000000000-(grid_iter_vec->first - input_data.z_numboxes()*(input_data.x_numboxes()-1)), particles_to_be_sent_east[grid_iter_vec->first]);
box_sent_x_info[grid_rank_lookup[grid_iter_vec->first - input_data.z_numboxes()*(input_data.x_numboxes()-1)]].insert(pair<int,int>(world.rank(),2000000000-(grid_iter_vec->first - input_data.z_numboxes()*(input_data.x_numboxes()-1))));
}
else if (!(grid_iter_vec->first-floor(grid_iter_vec->first/(input_data.xz_numboxes())*input_data.xz_numboxes())>input_data.xz_numboxes()-input_data.z_numboxes()-1))
{
reqs_x_send[counter_x_reqs++]=world.isend(grid_rank_lookup[grid_iter_vec->first + input_data.z_numboxes()], 2000000000-(grid_iter_vec->first + input_data.z_numboxes()), particles_to_be_sent_east[grid_iter_vec->first]);
box_sent_x_info[grid_rank_lookup[grid_iter_vec->first + input_data.z_numboxes()]].insert(pair<int,int>(world.rank(), 2000000000-(grid_iter_vec->first + input_data.z_numboxes())));
}
}
}
counter=0;
for (int i=0;i<world.size();i++)
{
//if (world.rank()!=i)
//{
reqs[counter++]=world.isend(i,1000000000,box_sent_x_info[i]);
reqs[counter++]=world.irecv(i,1000000000,box_received_x_info[i]);
//}
}
mpi::wait_all(reqs, reqs + world.size()*2);
//receive particles
//receive west particles
for (int j=0;j<world.size();j++)
{
multimap<int,int>::iterator received_info_iter;
for (received_info_iter=box_received_x_info[j].begin();received_info_iter!=box_received_x_info[j].end();received_info_iter++)
{
//receive the message
if (received_info_iter->second<1000000000)
{
//receive the message
world.recv(received_info_iter->first,received_info_iter->second,particles_received_west);
//loop through all the received particles and add them to the particle_grid for this processor
for (unsigned int i=0;i<particles_received_west.size();i++)
{
particle_grid[received_info_iter->second].insert(pair<int,Particle>(particles_received_west[i].global_part_num(),particles_received_west[i]));
if(particles_received_west[i].position().x()>grid_locations[received_info_iter->second][0] && particles_received_west[i].position().x()<grid_locations[received_info_iter->second][1])
{
particle_properties[particles_received_west[i].global_part_num()].particle_in_box()[received_info_iter->second]=true;
}
counter_received++;
counter_x_received++;
}
}
else
{
//receive the message
world.recv(received_info_iter->first,received_info_iter->second,particles_received_east);
//loop through all the received particles and add them to the particle_grid for this processor
for (unsigned int i=0;i<particles_received_east.size();i++)
{
particle_grid[2000000000-received_info_iter->second].insert(pair<int,Particle>(particles_received_east[i].global_part_num(),particles_received_east[i]));
if(particles_received_east[i].position().x()>grid_locations[2000000000-received_info_iter->second][0] && particles_received_east[i].position().x()<grid_locations[2000000000-received_info_iter->second][1])
{
particle_properties[particles_received_east[i].global_part_num()].particle_in_box()[2000000000-received_info_iter->second]=true;
}
counter_received++;
counter_x_received++;
}
}
}
}
mpi::wait_all(reqs_y_send, reqs_y_send + particles_to_be_sent_bottom.size()+particles_to_be_sent_top.size());
mpi::wait_all(reqs_z_send, reqs_z_send + particles_to_be_sent_south.size()+particles_to_be_sent_north.size());
mpi::wait_all(reqs_x_send, reqs_x_send + particles_to_be_sent_west.size()+particles_to_be_sent_east.size());
cout<<"x sent "<<counter_x_sent<<" and received "<<counter_x_received<<" from rank "<<world.rank()<<endl;
cout<<"rank "<<world.rank()<<" sent "<<counter_sent<<" and received "<<counter_received<<" and removed "<<counter_removed<<endl;
cout<<"done passing"<<endl;
}
I only posted some of the code (so ignore the fact that some variables may appear to be undefined, as they are in a portion of the code I didn't post)
When I run the code (on the machine in which it fails), I get done passing but not done passing particles
I am lost as to what could possibly cause a segmentation fault between the end of the called function and the next line in the calling function and why it would happen on one machine and not another.

If you're crashing between the end of a function and the subsequent line in the caller, you're probably crashing in the destructor of a local variable. You need to run the program in a debugger to find out which object's destructor is crashing.

There are a couple of possibilities:
You actually are returning, but cout is buffered by the OS so you don't see "done passing particles" because the application crashes first.
You have some local class that has a destructor that is seg faulting.
Try running it in a debugger to find out where it is actually crashing.
Edit:
Since you've mentioned you're using gcc, add the -g flag and run it with gdb. Gdb will then tell you exactly where it's going wrong (probably a null dereference).

Just in case anyone comes back to this later. I updated to the newest version of boost mpi(at the time), 1.50 and this issue went away. Not much of a solution, but it worked.

Related

Raycast check crashing UE5

I am trying to check what a multi line trace by channel is hitting by printing every hit object's name to the log, however the engine keeps crashing due to (I assume) a memory error.
I've tried only printing the first object, which works, but since this a multi line trace I would like to check every object that is being hit
Here is my code:
TArray<FHitResult> hits = {};
ECollisionChannel channel(ECC_GameTraceChannel1);
FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner());
GetWorld()->LineTraceMultiByChannel(
OUT hits,
camWorldLocation,
end,
channel,
TraceParams
);
DrawDebugLine(GetWorld(), camWorldLocation, end, FColor::Green, false, 2.0f);
if (!hits.IsEmpty())
{
for (int i = 0; i < sizeof(hits); i++)
{
if (&hits[i] != nullptr) {
if (hits[i].GetActor() != nullptr)
{
UE_LOG(LogTemp, Error, TEXT("Line trace has hit: %s"), *(hits[i].GetActor()->GetName()));
}
}
else
{
break;
}
}
}
sizeof(hits) gives you the size of the C++ object in bytes, not the number of items in the container.
You need to use
for (int i = 0; i < hits.Num(); i++)

return does not stop function, Recursive function issue? (programming exercise, Dynamic Programming, Levenshtein Back-trace)

the printOptimalAlignment function is misbehaving. goto and return will not exit when the function reaches location (1,1)... where it should end, no crash and it stops at seemingly an arbitrary location of (6,6)... because for some reason it increments at the end of the function even though there is no increment-er for the values int yL, int xL, (but I don't follow why it calls itself if it gets to the end of the function without any "hits" on the if statements.
Full code:
https://repl.it/#fulloutfool/Edit-Distance
void printOptimalAlignment(int** arr, string y, string x,int yL, int xL){
int I_weight=1, D_weight=1, R_weight=1;
bool printinfo_allot = 1,printinfo = 1;
if(printinfo_allot){
cout<<"Location: "<<"("<<xL<<","<<yL<<")"<<"-------------------------------\n";
cout<<"Same check Letters: "<<x[xL-2]<<","
<<y[yL-2]<<"("<<(x[xL-2] == y[yL-2])<<")"<<"\n";
cout<<"LL: "<<"("<<xL-1<<","<<yL<<")"
<<":"<<arr[yL][xL-1]
<<":"<<(arr[yL][xL-1]+I_weight)
<<":"<<(arr[yL][xL])
<<":"<<(((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1)
<<":"<<(yL>=1 && xL>=1)<<"\n";
cout<<"xL state:"<<((&x[xL]))<<":"<<(x[xL-1])<<"\n";
cout<<"yL state:"<<((&y[yL]))<<":"<<(y[yL-1])<<"\n";
string tx = &x[xL];
cout<<x.length()<<","<<(tx.length()+1)<<"\n";
}
string tx = &x[xL]; // slopy hotfix
if(x.length()==(tx.length()+1)){
cout<<"return functionality not working?-=-=-=-=-=-=-=-=\n";
cout<<"-> Prep last, current distance = "<<arr[yL][xL] <<"\n";
return;
//printOptimalAlignment(arr,y,x,yL-1,xL-1);
//cant use this goto... but where does it go?
//goto because_Im_a_terrible_person;
throw "how?... breaking rules... make it stop";
}
if(yL>=1 && xL>=1 && (x[xL-2] == y[yL-2]) == 1){
if(printinfo){
cout<<"-> Same (same char), current distance = "<<arr[yL][xL] <<"\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL-1);
}
if(yL>=1 && xL>=1 && (arr[yL-1][xL-1] == arr[yL][xL])){
if(printinfo){
cout<<"-> Swap (same int), current distance = "<<arr[yL][xL] <<"\n";
if(arr[yL-1][xL-1]==0)cout<<"---this is last---\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL-1);
}
if(yL>0 && xL>0 && (arr[yL-1][xL]+D_weight == arr[yL][xL])){
if(printinfo){
cout<<"-> Delete, current distance = "<<arr[yL][xL]<<"\n";
}
printOptimalAlignment(arr,y,x,yL-1,xL);
}
//really weird ((yL>1 && xL>1) && (((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1))
//not true if it is?
bool seperate = (((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1);
if(yL>=1 && xL>=1){
if((((arr[yL][xL-1]+I_weight) == arr[yL][xL])==1) && (true)){
if(printinfo){
cout<<"-> Insert, current distance = "<<arr[yL][xL]<<"\n";
cout<<"Next Location1: "<<"("<<xL-1<<","<<yL<<")"<<"\n";
}
printOptimalAlignment(arr,y,x,yL,xL-1);
return;
//how does it get here... also return gets ignored... prob another stack issue
cout<<"insert function broke?????? # (1,1) ???????????????\n";
//return;
}
}
return;
cout<<"END... Hopefully.. if you see this Something went wrong\n";
because_Im_a_terrible_person:
cout<<"QUIT\n";
}
I suspect your problem is that your function calls itself and you don't appear to be taking into account what should happen next after that call to itself finishes. So you get to your finish condition where you say the return doesn't work, but it does... it just returns to where you left off in the previous call to printOptimalAlignment, which still might do something before returning to its caller, and so on. You have three different sites where you recursively call printOptimalAlignment that aren't immediately followed by a return statement, and at any of these it might be that the code will continue and trigger another of your conditional blocks.

Stop arduino loop when a condition is active

I need my code to stop in the loop, i have tried to put in a break but the method sendToGCM() continues. I only want the method to be executed once, the stop while the condition
void loop()
{
// Other code here giving temp a value
if (temp > 22)
{
status = false;
value["status"] = status;
while (temp > 22)
{
sendToGCM(); // Sends push notification
break;
}
}
else
{
status = true;
value["status"] = status;
}
}
So if I understood you correctly, if the temperature goes 22 degrees you want to send a message, but only the first time. If you break the loop, you still enter it if you the loop() function is executed again.
In order to achieve what you want to do, you code will need to look something like this
boolean message_sent;
void loop() {
...
if(temperature > 22 && !message_sent) {
sendToGCM();
message_sent = true;
}
}
If you want to send a message every time the temperature rises over 22 degrees you would need something like this
boolean message_sent;
boolean was_under_22;
void setup() {
...
was_under_22 = function_that_checks_if_temp_is_under_22();
...
}
void loop() {
...
if(temperature > 22 && was_under_22) {
if(!message_sent) {
sendToGCM();
message_sent = true;
was_under_22 = false;
}
} else {
was_under_22 = true;
message_sent = false;
}
}
EDIT: slightly adapted the code in response to Patrick Trentin's comment. The code assumes you only want to capture if the temperature rises above 22 degrees and that if the Arduino starts with over 22 degrees then no message is sent.
Your problem is that you are setting temp, then entering the loop that checks that value. A simple solution would be to update the temp value inside the while loop, to give the application a chance to break out of the while loop.
Example:
void loop()
{
// Other code here giving temp a value
if (temp > 22)
{
status = false;
value["status"] = status;
while (temp > 22)
{
sendToGCM(); // Sends push notification
//Additional code to set the value of temp, allowing the value to
//be greater than 22.
}
}
else
{
status = true;
value["status"] = status;
}
}
Please note that the above example is intended to continuously send the push notification while the temp value is over 22. If that's not the intention, just remove the sendToGCM() from the while loop. You will still only send it if the temp is greater than 22, since you have the if check.

SFML Button Not Working

Under my button class, I have this function that checks if the mouse is within the bounds of the button:
bool Button::isMouseOver(int mousePosX, int mousePosY) {
if (button.getPosition().x < mousePosX &&
button.getPosition().x + button.getSize().x > mousePosX &&
button.getPosition().y < mousePosY &&
button.getPosition().y + button.getSize().y > mousePosY) {
return true;
}
return false;
}
And then under my main cpp file I have this logic used to activate the function:
int mousePosX = sf::Mouse::getPosition().x;
int mousePosY = sf::Mouse::getPosition().y;
switch (Event.type) {
case sf::Event::Closed:
window.close();
case sf::Event::MouseButtonPressed:
if (btnPlay.isMouseOver(mousePosX, mousePosY)) {
std::cout << "True\n";
}
}
but for some reason, nothing happens. And I know that this can work, because I have the same exact code in one of my other games and it works fine.
Slightly off topic, you comment
And I know that this can work, because I have the same exact code in
one of my other games and it works fine.
triggered me to think You might want to consider generalizing this and making something like
bool IsInside(windowPos wp, windowSize ws, someOtherPos sop) {
if (wp.x < sop.X &&
wp.x + ws.x > sop.X &&
wp.y < sop.Y &&
wp.y + ws.y > sop.Y) {
return true;
}
return false;
}
bool Button::isMouseOver(Vector2i mousePos) {
return IsInside(getPosition(), getSize(), mousePos) ;
}
Note types in IsInside are not exact and might actually be the same ( Vector2i ).
This also makes testing easier for correctness and removes a source of errors with copied code.

LinearHashTable iter not dereferencable and iter not

Hy all :)
I am using 1.5.4-all (2014-10-22) in my VC++ project (Microsoft Visual C++ Compiler 18.00.21005.1 for x86 platform).
My problem is that I get the following error message after some time. The time, after which the error occurs differ quiet a lot - sometimes it happens after 30 secs and sometimes after 5 minutes.
I could locate the source for the error in the LinearHashTable.h file at line 214:
I have the following method where a Shot (struct) is added to the table:
void ShotSimulationService::SimulateShot(Shot shot) {
MutexThreadLock.lock();
shots.insert(ShotsSetType::ValueType(SimulationShot(shot)));
errorCount = 0;
MutexThreadLock.unlock();
}
The call of SimulateShot is from another thread than the handling of the following code:
void ShotSimulationService::Update(WebcamService* observable) {
if (shots.empty()) {
return;
}
try {
Mat frame = observable->GetLastImage().clone();
ShotsSetType::Iterator iter = shots.begin();
vector<Shot> deleteShots;
errorCount++;
while (iter != shots.end()){
if (iter->SimulateStartExplosion()) {
//simulate gun explosion
OverlayImage(frame, gunShotImg, iter->startPoint);
}
//simulate explosion
SimulationShot::SimulationHitStatus status = iter->status;
if (status == SimulationShot::SimulationHitStatus::UNKNOWN) {
if (detectionService.HasShotHitPlayer(frame, *iter)) {
iter->status = SimulationShot::HIT_PLAYER;
iter->SetCurrentPointAsEndoint();
//Notify that player was hit
playerHitQueue.enqueueNotification(new PlayerHitNotification(iter->hitPlayer));
}
}
if (iter->SimulateEndExplosion()) {
if (status == SimulationShot::HIT_PLAYER) {
int explosionx = iter->endPoint.x - robotExplosionHalfXSize > 0 ? iter->endPoint.x - robotExplosionHalfXSize : 0;
int explosionY = iter->endPoint.y - robotExplosionHalfYSize > 0 ? iter->endPoint.y - robotExplosionHalfYSize : 0;
OverlayImage(frame, robotExplosionImg, Point2i(explosionx, explosionY));
}
else {
// status == SimulationShot::HIT_WALL or UNKNOWN
int explosionx = iter->endPoint.x - wallExplosionHalfXSize > 0 ? iter->endPoint.x - wallExplosionHalfXSize : 0;
int explosionY = iter->endPoint.y - wallExplosionHalfYSize > 0 ? iter->endPoint.y - wallExplosionHalfYSize : 0;
OverlayImage(frame, robotExplosionImg, Point2i(explosionx, explosionY));
if (status != SimulationShot::HIT_WALL) {
iter->status = SimulationShot::HIT_WALL;
}
}
if (iter->IsSimulationFinished()) {
deleteShots.push_back(*iter);
}
}
else {
//simulate bullet
OverlayImage(frame, cheeseImg, iter->GetNextShotPoint());
}
++iter;
}
//delete finished simulations
MutexThreadLock.lock();
for each (Shot shot in deleteShots)
{
shots.erase(shot);
}
MutexThreadLock.unlock();
}
catch (cv::Exception& e) {
Logger& logger = Logger::get("Test");
logger.error(e.what());
}
}
The Update method is called quiet often - always when a new webcam frame is available.
The callstack of the error starts in the following line:
if (iter->SimulateEndExplosion()) {
In the method SimulateEndExplosion only members of the struct were used:
bool SimulateEndExplosion() {
if (status == HIT_PLAYER) {
currPercentage = 1.0;
return true;
}
if (currPercentage < 1.0) {
return false;
}
++endExplosionCtr;
return endExplosionCtr <= maxEndExplosions;
}
Does anybody have an idea why this problem occurs?
Any help and any feedback is welcome!! I have absolutly no idea what is going wrong here :(
Thanks!
Iterating in one thread and inserting in another without protecting the operations with mutex in both threads will cause this problem; when you insert, iterator will be invalidated and you will get the assertion failure. You should protect both insertion and iteration with mutex.
Also, the way you are using mutex is not safe because mutex will not be unlocked if an exception is thrown between lock() and unlock(). Use ScopedLock instead and RAII will do the job automatically and safely in all cases:
void ShotSimulationService::SimulateShot(Shot shot) {
Mutex::ScopedLock lock(MutexThreadLock);
shots.insert(ShotsSetType::ValueType(SimulationShot(shot)));
errorCount = 0;
// unlock will be called by ScopedLock destructor
}