我目前正在学习如何使用c ++进行多线程处理,以及使用boost :: thread进行多线程处理。 我用它来做一个简单的游戏引擎,运行三个线程。
其中两个线程正在读取和写入相同的变量,这些变量存储在我称之为PrimitiveObjects的内容中,基本上是球,板,盒等。
但我真的无法让它工作,我认为问题是两个线程同时试图访问相同的内存位置,我试图使用互斥锁来避免这种情况,但是现在我没有运气,这有效,但如果我垃圾邮件,我最终会遇到这个例外:
First-chance exception at 0x00cbfef9 in TTTTT.exe: 0xC0000005: Access violation reading location 0xdddddded.
Unhandled exception at 0x77d315de in TTTTT.exe: 0xC0000005: Access violation reading location 0xdddddded.
这些是我正在使用的对象内部的函数,调试器也将它们归咎于异常。
int PrimitiveObj::setPos(glm::vec3 in){
boost::try_mutex::scoped_try_lock lock(myMutex);
if ( lock)
{
position = in;
return 1;
}
return 0;
}
glm::vec3 PrimitiveObj::getPos(){
boost::try_mutex::scoped_try_lock lock(myMutex);
if ( lock)
{
glm::vec3 curPos = position;
return curPos;
}
return glm::vec3(0,0,0);
}
这是我用来生成每个primitiveobj的函数。 (更新)
void generatePrimitive(){
PrimitiveObj *obj = new PrimitiveObj();
obj->generate();
obj->setPos(getPlayerPos()+getEye()*4.0f);
prims.push_back(std::shared_ptr<PrimitiveObj>(obj));
}
有什么想法吗? 编辑:新功能(2),myMutex现在是对象的私有。添加了我用来生成原始对象的函数。
编辑:
这是堆栈指向的代码,它在物理线程中运行:
nr = getNumberOfPrimitives();
double currentTime = glfwGetTime();
float deltaTime = float(currentTime - lastTime);
for(int r = 0; r < nr; r++) {
prop = getPrimitive(r);
glm::vec3 pos = prop->getPos()+glm::vec3(0,1.0f*Meter/deltaTime,0);
prop->setPos(pos);
}
其他相关代码:
int getNumberOfPrimitives(){
return prims.size();
}
PrimitiveObj * getPrimitive(int input) {
return prims[input];
}
答案 0 :(得分:2)
第一个想法是你正在调用的PrimitiveObj
未初始化,如下所示:
PrimitiveObj* myObject;
myObject->getPos();
您拥有的异常很可能是访问未初始化的指针变量(设置为0xddddddd,因此开发人员将其识别为未初始化)并访问其上的成员,该成员偏移0x10(= 16)字节。
如果在同时从不同线程读取和写入同一对象时访问诸如std:vector之类的对象,也会发生访问异常,但该位置通常是一个以零开头并且可以整除的随机数字乘以4(例如0x004da358)。
为什么会这样?调试代码通常使用一些可识别但随机的数字(0xdddddddd,0xbaadfood,0xfefefefe等)初始化内存。它们是随机的,因为如果变量总是相同的,例如,始终初始化为0,这可能导致开发人员错过某些变量未初始化且代码将在发布中停止工作的事实。它们很容易识别,因此我们可以一眼就看出这个数字来自未初始化的记忆。
以前有效的指针指向堆地址空间,它通常从一个较小的数字开始并计数。如果在堆上分配了多个对象,则在正常操作中,每个对象在一个可被4,8,16等整除的内存地址上对齐。对象的成员也在4字节边界上对齐,这就是导致访问冲突的原因通过访问以前有效的内存通常是以零开头的地址,并且可以被4整除。
请记住,这些是经验法则,可以而且应该用于指向正确的方向,但它们并不是硬性规定。此外,它们指的是调试环境。发布环境具有非常不同的规则来猜测哪些访问冲突是由什么引起的。