2015-09-21 17 views
0

我正在製作一個象棋遊戲程序。作爲它的一部分,我寫了一個靜態方法,該方法應該通過調用自己的各種版本的電路板,一個Piece * board [8] [8],遞歸地操作其輸入,並傳回位置在std :: unique_ptr內的板的「最佳」版本,這是該方法的返回類型。返回後無法保持動態分配的內存一致

節點被定義爲這樣:

class node 
{ 
    public: 
    node(); 
    ~node(); 
    std::unique_ptr<node> l; 
    std::unique_ptr<node> r; 
    std::unique_ptr<node> m; 
    node * best; 
    int bestval; 

    Piece * (*board)[8]; 
}; 

的目標是最終要遞歸方法的初始調用的結果包含一個「最佳」值,其通過鏈接到的最佳路徑選擇整個鏈棋盤。然後我會畫出一系列結果的棋盤狀態。

作爲其中的一部分,董事會必須保留。無論在每個遞歸步驟中「獲勝」的板卡都被複制到動態存儲器中,並且返回的板指針(件*(*板)[012]節點聲明中)被設置爲該動態分配的存儲器。

這是像這樣做:那麼

std::unique_ptr<node> ret (new node); 
    Piece *** reboard = new Piece**[8]; 
    for (int i = 0; i < 8; i++) 
    { 
     reboard[i] = new Piece*[8]; 
    } 
    ...code to copy values to reboard and set other ret property values... 
    ret->board = reboard; 
    return ret; 

所有獲獎的國際象棋棋盤的本地值複製到reboard。這一切工作正常。如果我在此階段將所有reboard的值複製到全局板上,則返回並直接將該全局板繪製到屏幕上,這會得出正確的結果。同樣,如果我將ret-> board指向該全局板,然後將值複製到全局板並返回,則會繪製正確的值。

但是,如果我做什麼我寫上面,並試圖畫ret->板,我得到無效的內存訪問錯誤,在我的畫法,我拉我的頭髮試着對這個問題下。看起來在返回之後,指向的內存被以某種方式回收。在這個應該只是數據的內存中,我看到數組中的條目似乎指向msctf.dll中的代碼以及其他無效的數據指針。我認爲它被垃圾回收回收,所以我甚至試圖在我看到的任何指針上放入一些std :: declare_reachable調用,但這並沒有幫助。

任何人都可以注意到這裏發生了什麼?不應該動態分配記憶棒,直到我釋放它爲止?

+0

看看比特板;他們比你的數據結構更好。而且,在國際象棋引擎代碼中應該只有很少的堆。我只對轉置表和線程安裝期間使用堆分配。上下游戲樹不需要堆分配 - 所有事情都應該預先分配。 – VoidStar

回答

0

std :: unique_ptr是一個智能指針,它通過指針保留對象的唯一所有權,並在unique_ptr超出範圍時銷燬該對象。沒有兩個unique_ptr實例可以管理同一個對象。

來源:cppreference.com

換句話說,你是儘快釋放內存爲你打return,然後返回垃圾。當然,它會導致訪問衝突,試圖解除引用內存。

+0

有一個對初始遞歸調用的返回指針的全局引用,並且所有後續調用都保存在其被調用者的返回指針中,所以唯一指針實際上是按預期方式持續存在的。我打算證明這一點,指出ret->董事會全球董事會工作良好。 – caffeineinfused

+0

我會用一句話來再說一遍:當'ret'超出範圍時,內存就會被釋放。如果'unique_ptr'的語義不適合你,請退出爭論並使用正確的智能指針類。特別是如果你想分享它(和你一樣),使用'shared_ptr'。 – Blindy