В настоящее время я учусь многопоточности с 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);
}
Это функция, которую я использую для генерации каждого примитива. (Обновлено)
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];
}
Первая идея заключается в том, что ваш PrimitiveObj
то, что вы звоните, неинициализировано, что-то вроде этого:
PrimitiveObj* myObject;
myObject->getPos();
Исключением является то, что вы, скорее всего, обращаетесь к неинициализированной переменной-указателю (равной 0xdddddddd, чтобы разработчик распознал ее как неинициализированную) и обращаетесь к элементу, который смещен на 0x10 (= 16) байтов.
Исключения доступа также могут возникать, если вы обращаетесь к объектам, таким как std: vector, при чтении и записи из разных потоков в один и тот же объект в одно и то же время, но часто это более случайное число, которое начинается с нулей и делится на 4 ( например, 0x004da358).
Почему это так? Код отладки часто инициализирует память некоторыми узнаваемыми, но случайными числами (0xdddddddd, 0xbaadfood, 0xfefefefe и т. Д.). Они случайны, потому что если переменные всегда будут одинаковыми, например, всегда инициализируется 0, что может привести к тому, что разработчик упустит тот факт, что некоторые переменные не инициализированы и код перестанет работать в выпуске. Их легко распознать, поэтому мы можем сразу увидеть, что число исходит из неинициализированной памяти.
Ранее действительные указатели указывают на адресное пространство кучи, которое обычно начинается с несколько меньшего числа и подсчитывается. Если в куче размещено несколько объектов, при нормальной работе каждый объект выравнивается по адресу памяти, кратному 4, 8, 16 и т. Д., Члены объекта также выравниваются по 4-байтовым границам, поэтому нарушения доступа вызвали при доступе к ранее действительной памяти часто на адреса, которые начинаются с нулей и делятся на 4.
Помните, что это эмпирические правила, которые можно и нужно использовать, чтобы указать вам правильное направление, но они не являются жесткими и быстрыми правилами. Также они относятся к средам отладки. В средах выпуска очень разные правила, чтобы угадать, какое нарушение прав доступа вызвано чем.
Других решений пока нет …