LinearHashTable iter not dereferencable and iter not

萝らか妹 提交于 2019-12-13 06:58:35

问题


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!


回答1:


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
    }


来源:https://stackoverflow.com/questions/27851837/linearhashtable-iter-not-dereferencable-and-iter-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!