2012-03-21 52 views
0

我有一個國際象棋遊戲,最初使用stl列表來存儲我切換到矢量以獲得更好性能的棋子。我明白,載體不支持多態,所以爲了解決這個問題,我正在存儲一個向量<Unit *>而不是<Unit>。我所有的棋子對象(Pawn,Rook,Bishop等)都從Unit類繼承而來。用一個派生類到另一個派生類的指針交換矢量元素

但是,似乎仍然存在向量和堆損壞的問題。我想我已經跟蹤它到以下功能:

Unit *ChessGame::PromoteUnit(Unit *_oldUnit, UnitType _newType) 
{ 

vector<Unit *> &army = (_oldUnit->m_gameColor == WHITE) ? m_whiteArmy : m_blackArmy; 
Unit *newUnit = NULL; 

for (unsigned int i = 0; i < army.size(); ++i) 
{ 
    if (army[i]->m_subId == _oldUnit->m_subId) 
    { 
     if (_newType == QUEEN && _oldUnit->m_gameColor == WHITE) 
     { 
      newUnit = new Queen(*_oldUnit); 
      newUnit->ActiveTexture_(m_textureMan->TextureId_(WhiteQueen)); 
     } 
     else if (_newType == KNIGHT && _oldUnit->m_gameColor == WHITE) 
     { 
      newUnit = new Knight(*_oldUnit); 
      newUnit->ActiveTexture_(m_textureMan->TextureId_(WhiteKnight)); 
     } 
     else if (_newType == QUEEN && _oldUnit->m_gameColor == BLACK) 
     { 
      newUnit = new Queen(*_oldUnit); 
      newUnit->ActiveTexture_(m_textureMan->TextureId_(BlackQueen)); 
     } 
     else if (_newType == KNIGHT && _oldUnit->m_gameColor == BLACK) 
     { 
      newUnit = new Knight(*_oldUnit); 
      newUnit->ActiveTexture_(m_textureMan->TextureId_(BlackKnight)); 
     } 

     newUnit->m_wasPawn = true; 
     delete army[i]; 
     army[i] = newUnit; 
     break; 
    } 
} 

m_selectedUnit = newUnit; 

return newUnit; 
} 

由於指針,無論它指向只有4個字節是有一個原因一個STL向量仍然有在類似情況下的一個問題這個? My Pawn對象的大小比Knight或Queen提升了8個字節,可能會解釋我得到的奇怪內存錯誤。當我備份我把歷史和打我的降級功能,以扭轉推廣:

Unit *ChessGame::DemoteUnit(Unit *_oldUnit, UnitType _newType) 
{ 
COUT("ChessGameManager::_DemoteUnit(Unit *, UnitType)"); 

vector<Unit *> &army = (_oldUnit->m_gameColor == WHITE) ? m_whiteArmy : m_blackArmy; 
Unit *newUnit = NULL; 

for (unsigned int i = 0; i < army.size(); ++i) 
{ 
    if (army[i]->m_subId == _oldUnit->m_subId) 
    { 
     newUnit = new Pawn(); 
     newUnit->m_wasPawn = false; 

     if (_oldUnit->m_gameColor == WHITE) 
      newUnit->ActiveTexture_(m_textureMan->TextureId_(WhitePawn)); 

     newUnit->m_gameColor = _oldUnit->m_gameColor; 
     newUnit->MobilityValid_(false); 
     newUnit->Color_(RvColor::ClrWhite); 
     newUnit->m_square = _oldUnit->m_square; 
     newUnit->m_captured = false; 
     newUnit->m_origin = _oldUnit->m_origin; 
     newUnit->m_subId = _oldUnit->m_subId; 
     newUnit->m_visible = true; 

     //newUnit->m_square->m_unit = newUnit; 

     delete army[i]; 
     army[i] = newUnit; 
     break; 
    } 
} 

return newUnit; 
} 

它的字面崩潰上:

newUnit = new Pawn(); 

步入新典當()導致它新的內部崩潰運算符試圖使用malloc來保留堆內存。無論如何,我認爲它還與我對矢量網絡的工作原理缺乏完全理解有關。我知道它與我的Pawn()構造函數無關,因爲它在遊戲板的初始化過程中被調用了很多次。

+0

看起來像內存錯誤。如果你在Linux或OS X上,我會建議使用valgrind來消除任何動態內存訪問問題:http://valgrind.org/ – Alex 2012-03-21 20:20:13

+0

這些是唯一運行的兩種方法? – 2012-03-21 20:31:03

+0

請將您的程序縮減爲顯示錯誤的最短完整程序,並在您的問題中發佈** complete **,** short **程序。請參閱http://sscce.org獲取更多信息。 – 2012-03-21 21:29:27

回答

0

我懷疑但無法從您共享的信息中證明您的拷貝構造函數和拷貝賦值操作符ChessGame做了m_whiteArmym_blackArmy的淺拷貝。 (注意:如果你沒有提供拷貝構造函數或拷貝賦值操作符,編譯器爲你提供它們,編譯器提供的拷貝會做淺拷貝。)

你違反了Rule of Three

  • 決不復制ChessGame對象:

    你可以解決這個問題。

  • 通過執行以上操作:
    • (pre-C++ 11):聲明和不定義複製構造函數和複製賦值運算符。
    • (C++ 11):在複製構造函數和複製賦值運算符聲明之後指定= delete
  • 改變你的指針智能指針(如std::shared_ptr),或
  • 在你的拷貝構造函數實現一個深拷貝和複製賦值運算符。
+0

我實際上從來沒有在我的代碼中複製ChessGame類,所以我不認爲這是問題,我只能通過指針傳遞給方法或函數或參考。 – 2012-03-21 21:23:02

+0

我想我主要是問,如果上面的代碼看起來是合法的我如何嘗試使用矢量和基於反饋我猜我發佈的內容看起來確定,這意味着我需要嘗試看看別處。現在我最大的問題是想知道如何去調試一個錯誤,這個錯誤會在「新」中出現:(如果我的記憶超出界限並導致現有的連續分配被加入,將會很難要知道在哪裏設置斷點,如果我有一個線程,它將是一回事,但我不會。 – 2012-03-22 03:16:12

+0

我將減少像羅布說的代碼,然後重新發布我的發現後感謝傢伙,感謝所有的幫助! – 2012-03-22 03:52:31

相關問題