2012-12-13 98 views
3

我目前正在學習如何使用C++進行多線程,以及使用boost :: thread進行多線程。 我使用它作爲一個簡單的遊戲引擎,運行三個線程。Boost ::線程互斥問題:嘗試鎖定,訪問衝突

線程中的兩個讀取和寫入到相同的變量,其存儲裏面的東西我打電話PrimitiveObjects,basicly球,盤,盒等

,但我不能真正得到它的工作,我覺得問題是這兩個線程試圖同時訪問相同的內存位置,我試圖避免使用互斥鎖,但現在我沒有運氣,這工作有些時候,但如果我垃圾它,我最終但有以下例外情況:

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現在對該對象是私有的。增加了我用來生成primitiveobjects的函數。

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

第一個想法是您的PrimitiveObj您呼叫未初始化,這樣的事情:

PrimitiveObj* myObject; 
myObject->getPos(); 

你有例外的情況是最有可能你訪問一個未初始化的指針變量(設置爲0xdddddddd因此開發者將其視爲未初始化)和它在訪問成員這被0x10(= 16)字節偏移。

訪問異常也可能發生,如果您訪問對象,如std:vector,同時讀取和寫入從不同的線程同時對同一個對象,但位置通常是一個更隨機的數字以零開頭,是可被4整除(例如0x004da358)。

這是爲什麼?調試代碼通常使用一些可識別的隨機數(0xdddddddd,0xbaadfood,0xfefefefe等)初始化內存。它們是隨機的,因爲如果變量總是相同的,例如總是初始化爲0,這可能會導致開發人員錯過某些變量未初始化並且代碼在發佈中停止工作的事實。它們很容易識別,所以我們可以一眼就知道這個數字來自未初始化的內存。

以前有效的指針指向堆地址空間,通常從較低的數字開始計數。如果在堆上分配了多個對象,那麼在正常操作中,每個對象都是對齊的,在可由4,8,16等整除的內存地址上,對象的成員也在4字節邊界上對齊,這就是爲什麼導致訪問衝突的原因通過訪問以前有效的內存通常是以零開始並且可以被4整除的地址。

請記住,這些是可以並且應該用來指向正確方向的規則,但它們不是硬性規則和快速規則。另外,它們指的是調試環境。發佈環境具有非常不同的規則來猜測哪些訪問衝突是由什麼引起的。

+0

感謝您的回覆!該對象已初始化。所以,即使我認爲你的第二個建議是正確的道路,如果我使互斥體專用於對象而不是函數,代碼是否可以工作?用新代碼更新op! – user1419305

+2

將互斥鎖作爲對象的成員將允許鎖來保護代碼。 您所遇到的異常很可能是您訪問未初始化的指針變量(設置爲0xdddddd,以便開發人員將其識別爲未初始化)並訪問其上偏移0x10個字節的成員。 – Peter

+0

彼得斯答案是完全正確的,但互斥錯誤不會導致訪問衝突。我敢肯定,你已經建議,在未初始化的指針上調用函數。 – Archy