gpt4 book ai didi

c++ - LinearHashTable iter 不可取消引用且 iter 不可

转载 作者:行者123 更新时间:2023-11-28 06:29:38 30 4
gpt4 key购买 nike

大家好 :)

我在我的 VC++ 项目中使用 1.5.4-all (2014-10-22)(适用于 x86 平台的 Microsoft Visual C++ 编译器 18.00.21005.1)。

我的问题是一段时间后收到以下错误消息。错误发生的时间相差很大 - 有时发生在 30 秒后,有时发生在 5 分钟后。 enter image description here

我可以在 LinearHashTable.h 文件的第 214 行找到错误的来源: enter image description here

我有以下方法,其中将镜头(结构)添加到表中:

    void ShotSimulationService::SimulateShot(Shot shot) {
MutexThreadLock.lock();
shots.insert(ShotsSetType::ValueType(SimulationShot(shot)));
errorCount = 0;
MutexThreadLock.unlock();
}

SimulateShot 的调用来自另一个线程,而不是处理以下代码:

    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());
}
}

Update 方法经常被安静地调用 - 总是在有新的网络摄像头帧可用时调用。

错误的调用堆栈从以下行开始:

    if (iter->SimulateEndExplosion()) {

在 SimulateEndExplosion 方法中只使用了结构的成员:

        bool SimulateEndExplosion() {
if (status == HIT_PLAYER) {
currPercentage = 1.0;
return true;
}

if (currPercentage < 1.0) {
return false;
}

++endExplosionCtr;
return endExplosionCtr <= maxEndExplosions;
}

有人知道为什么会出现这个问题吗?

欢迎任何帮助和反馈!!我完全不知道这里出了什么问题:(

谢谢!

最佳答案

在一个线程中迭代并在另一个线程中插入而不在两个线程中使用互斥锁保护操作将导致此问题;当你插入时,迭代器将失效,你将得到断言失败。您应该使用互斥锁来保护插入和迭代。

此外,您使用互斥量的方式也不安全,因为如果在 lock() 和 unlock() 之间抛出异常,互斥量将不会被解锁。使用 ScopedLock 代替,RAII 将在所有情况下自动安全地完成工作:

void ShotSimulationService::SimulateShot(Shot shot) {
Mutex::ScopedLock lock(MutexThreadLock);
shots.insert(ShotsSetType::ValueType(SimulationShot(shot)));
errorCount = 0;
// unlock will be called by ScopedLock destructor
}

关于c++ - LinearHashTable iter 不可取消引用且 iter 不可,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27851837/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com