3

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];
}
user1419305
  • 468
  • 8
  • 16

1 Answers1

2

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.

Peter
  • 5,608
  • 1
  • 24
  • 43
  • Thanks for the reply! The object is initialized. So im thinking you are on the right path with your second suggestion, will the code work if i made the mutex private to the object instead of to the function? Updated op with new code! – user1419305 Dec 13 '12 at 23:06
  • 2
    Putting the mutex as member of the object will allow the lock to protect the code. The exception you have is most likely you accessing an uninitialized pointer variable (set to 0xddddddd so the developer recognizes it as uninitialized) and accessing a member on it that is offset by 0x10 bytes. – Peter Dec 13 '12 at 23:10
  • Peters answer is fully correct, but the mutex errors will not lead to the access violation. I am pretty sure you call the functions on uninitialised pointer's as peter already suggested. – Archy Dec 13 '12 at 23:12
  • So the i wont get any access violations by reading the same location from two threads at the same time? – user1419305 Dec 13 '12 at 23:14
  • There is a chance to get the access exception by reading and writing a complex object from two threads at the same time. For example if you delete a std::vector (writing) and read it at the same time this can result in an access exception. In these cases the addresses of the access exception often but not always look more random than 0xdddddded. Reading memory from multiple threads at the same time is safe, as long as it's not written to at the same time. – Peter Dec 13 '12 at 23:18
  • As there is only position data at that location you can get outdated or corrupt data which could lead to everything if you do strange things with the data but it will definitely not give you an access violation when reading it. – Archy Dec 13 '12 at 23:19
  • 1
    Attach a debugger and check where exactly the exception is thrown. – Archy Dec 13 '12 at 23:34
  • Good point Archy. @user1419305 There's probably already a question on Stackoverflow on how to debug in your environment, but if you can't find one feel free to start a new question. – Peter Dec 13 '12 at 23:47
  • Thanks for the help, i print screened the errormessage: http://i222.photobucket.com/albums/dd273/mongoleif07/exception_prtscrn_zpsd4a352ef.png – user1419305 Dec 14 '12 at 14:22
  • Yes, the pointer to PrimitiveObj is definitely uninitialized. At the bottom left of the screenshot you can see the "this" pointer being 0xdddddddd. At the lower right you can open a currently hidden window "call stack" (where "output" is currently shown). That window shows you from where the function `getPos` function was called. That other function that calls getPos is the problem. – Peter Dec 14 '12 at 15:40
  • Thanks, its pointing at where i call getPos() inside the physics thread. I will update op with relevant code from there, this has been stuck in my mind for some time, but i cant find a solution. – user1419305 Dec 15 '12 at 23:33
  • Could using an array instead of a std::vector solve my problem? – user1419305 Dec 16 '12 at 13:10
  • In your version of visual studio, in debug, the vector would have thrown a different kind of exception if you'd have accessed an element that did not exist (unless you're in an enterprise environment with non-default settings, in which case the people there can help you). The pointer stored in the vector is not valid because it was the uninitialized 0xdddddddd when it was put in the vector. – Peter Dec 16 '12 at 15:17
  • Tried to use a shared_ptr instead, updated op with a new generatePrimitives() and a new picture of the errormessage, any ideas? I dont get why this wont initialize, first object spawns fine, after that the program crashes. – user1419305 Dec 19 '12 at 17:29