2012-12-13 2 views
3

현재 C++로 멀티 스레드하는 방법을 배우고 있으며, boost :: thread를 사용하고 있습니다. 3 개의 스레드를 실행하는 간단한 gameengine에 사용하고 있습니다. 스레드의Boost :: thread 뮤텍스 문제 : 잠금을 시도하여 액세스 위반을 시도하십시오.

두가 읽고 난 PrimitiveObjects, basicly 공, 접시, 상자 등

를 호출하지만 난 정말 일하러 가야하지 못할 뭔가 내부에 저장되어있는 같은 변수에 작성, 나는 생각 문제는 두 스레드가 동일한 memorylocation에 동시에 액세스하려고하는 것입니다. 뮤텍스 잠금을 사용하지 않으려 고했지만 지금은 아무런 운이 없는데,이 작업은 약간의 시간이 걸립니다.하지만 스팸 메일로 보내면 결국 끝납니다. 이 예외적으로

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

printscreen

어떤 아이디어 (업데이트)? 편집 : 새 기능 (2) 및 myMutex가 이제 개체 전용입니다. 프리미티브 개체를 생성하는 데 사용하는 함수를 추가했습니다.

Error

편집 :

이 스택에서 가리키는 코드이며,이 물리 스레드 내에서 실행된다

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

답변

2

첫 번째 아이디어는 귀하의당신이 호출 (210)는이 같은 초기화되지 :

PrimitiveObj* myObject; 
myObject->getPos(); 

당신이 예외는 (그래서 개발자가 초기화되지 않은 것처럼 그것을 인식 0xdddddddd로 설정) 초기화되지 않은 포인터 변수를 액세스하고 그 위에 멤버를 액세스 할 가능성이 높습니다 이는 0x10 (= 16) 바이트만큼 오프셋됩니다.

액세스 예외는 다른 스레드에서 동일한 객체로 동시에 읽고 쓰는 동안 std : vector와 같은 객체에 액세스 할 때도 발생할 수 있지만 위치는 종종 0으로 시작하는 더 무작위로 보이는 숫자입니다 4로 나눌 수 있습니다 (예 : 0x004da358).

왜 그런 경우입니까? 디버그 코드는 인식 할 수있는 임의의 숫자 (0xdddddddd, 0xbaadfood, 0xfefefefe 등)로 메모리를 초기화합니다. 변수가 항상 동일하면 (예 : 항상 0으로 초기화되므로 개발자가 일부 변수가 초기화되지 않고 코드가 릴리스에서 작동하지 않는다는 사실을 놓칠 수 있습니다. 그들은 쉽게 인식 할 수 있으므로 번호는 초기화되지 않은 메모리에서 온다는 것을 한눈에 알 수 있습니다.

이전 유효한 포인터는 힙 주소 공간을 가리키며 보통 힙 주소 공간을 가리키며 다소 낮은 숫자부터 시작하여 카운트 업합니다.힙에 여러 객체가 할당되면 정상 동작에서 각 객체는 4, 8, 16 등으로 나눌 수있는 메모리 주소에 정렬됩니다. 객체의 멤버도 4 바이트 경계에 정렬되므로 액세스 위반이 발생합니다 이전에 유효한 메모리에 액세스 한 것은 흔히 0으로 시작하고 4로 나눌 수있는 주소에 있습니다.

올바른 방향으로 사용자를 가리킬 수 있고 사용해야하는 엄지 손가락 규칙이지만, 어렵고 빠른 규칙. 또한 디버그 환경을 참조합니다. 릴리스 환경에는 어떤 액세스 위반이 무엇 때문에 발생했는지를 추측하는 것과는 매우 다른 규칙이 있습니다.

+0

답장을 보내 주셔서 감사합니다. 개체가 초기화됩니다. 그래서 당신이 두 번째 제안으로 올바른 길을 가고 있다고 생각한다면, 함수 대신 객체에 뮤텍스를 개인적으로 만든다면 코드가 작동할까요? 새로운 코드로 op를 업데이트했습니다! – user1419305

+2

뮤텍스를 객체의 멤버로 지정하면 잠금이 코드를 보호 할 수 있습니다. 예외는 초기화되지 않은 포인터 변수 (개발자가 초기화되지 않은 것으로 인식하도록 0xddddddd로 설정 됨)에 액세스하고 0x10 바이트만큼 오프셋 된 멤버에 액세스하는 것이 가장 가능성이 높습니다. – Peter

+0

Peters 대답은 완전히 정확하지만 뮤텍스 오류로 인해 액세스 위반이 발생하지는 않습니다. 피터가 이미 제안한 것처럼 초기화되지 않은 포인터의 함수를 호출하는 것이 좋습니다. – Archy

관련 문제