3
votes

I am currently learning how to multithread with c++, and for that im using boost::thread. I'm using it for a simple gameengine, running three threads.

Two of the threads are reading and writing to the same variables, which are stored inside something i call PrimitiveObjects, basicly balls, plates, boxes etc.

But i cant really get it to work, i think the problem is that the two threads are trying to access the same memorylocation at the same time, i have tried to avoid this using mutex locks, but for now im having no luck, this works some times, but if i spam it, i end up with this exception:

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.

These are the functions inside the object that im using for this, and the debugger is also blaming them for the exception.

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

This is the function im using to generate each primitiveobj. (updated)

void generatePrimitive(){
PrimitiveObj *obj = new PrimitiveObj();
 obj->generate();
obj->setPos(getPlayerPos()+getEye()*4.0f);
prims.push_back(std::shared_ptr<PrimitiveObj>(obj));
}

printscreen

Any ideas? Edit: New functions(2), and myMutex is now private to the object. Added the function i use to generate the primitiveobjects.

Error

Edit:

This is the code that the stack is pointing at, and this is running inside the physics thread:

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

}

Other relevant code:

int getNumberOfPrimitives(){
return prims.size();
}

PrimitiveObj * getPrimitive(int input) {
return prims[input];
}
1

1 Answers

2
votes

The first idea is that your PrimitiveObj that you are calling is uninitialized, something like this:

PrimitiveObj* myObject;
myObject->getPos();

The exception you have is most likely you accessing an uninitialized pointer variable (set to 0xdddddddd so the developer recognizes it as uninitialized) and accessing a member on it that is offset by 0x10 (=16) bytes.

Access Exceptions can also happen if you access objects such as std:vector while reading and writing from different threads to the same object at the same time, but the location is often a more random looking number that starts with zeros and is divisible by 4 (e.g. 0x004da358).

Why is that the case? Debug code often initializes memory with some recognizable yet random numbers (0xdddddddd, 0xbaadfood, 0xfefefefe, etc). They are random because if the variables would always be the same, e.g. always initialized to 0, which could cause the developer to miss the fact that some variables are not initialized and the code would stop working in release. They are easy to recognize so we can tell at a glance that the number comes from uninitialized memory.

Formerly valid pointers point to the heap address space, which usually starts from a somewhat low number and counts up. If multiple objects are allocated on the heap, in normal operation each object is aligned, on a memory address divisible by 4, 8, 16, etc. the members of an object are aligned on 4 byte boundaries as well, that's why access violations caused by accessing formerly valid memory are often on addresses that start with zeros and are divisible by 4.

Keep in mind that these are rules of thumb which can and should be used to point you in the right direction, but they are not hard and fast rules. Also, they refer to debug environments. Release environments have very different rules to guessing which Access Violation is caused by what.