2013-04-29 85 views
0

編輯:指針刪除崩潰

我已經實現了複製構造函數(都來自建議的答案)。我已經在我的控制器類中做了這個,以及它的子類中的等價版本。但是,這並沒有解決這個問題。此外,在removePawn()函數(程序中唯一稱爲刪除的地方)中的計數器和控制檯註釋表明它只被調用一次。

更詳細地說,每個子類都有一個實例(不是指針)。這些在我的world類中聲明。兩者都通過baseController類指針在類方法world中用作參數。問題是,雖然兩者都按照相同的順序進行相同的過程,但如果一個類調用了removePawn(),那麼程序會很好,並且會持續運行。但是,如果第二類具有removePawn()(特別刪除),它會在該指令處崩潰程序。

我也檢查過地址。分配後指針的地址與刪除點處的地址相同。

更多信息:當關閉程序時,如果玩家被殺死(刪除,然後給予一個新的棋子),我會得到一個分割錯誤。但是,如果程序啓動後關閉時沒有超過第一次刪除和最後一次刪除,那麼它運行得很好。

原創:

我對指針有點麻煩。我理解他們,並相信我的代碼是相當健壯的,但我似乎在調用這段代碼時完全崩潰。

Pawn是一個basePawn *,初始化爲NULL。

if (pawn != NULL) 
{ 
    cout << "Calling delete.\n"; 
    delete pawn; 
    pawn = NULL; 
} 

這是PS2程序的大學作業,所以我的調試僅限於基本打印到控制檯。

刪除的刪除線允許主新/刪除部分跑了幾次但它最終也崩潰(我想這是因爲已達到內存限制,但是我不能肯定)

我有檢查了所有通常的罪魁禍首,指針被初始化爲空,並且只刪除一次(新也總是被調用)。

我可能會犯一個相當明顯的錯誤,但我不知道。任何建議都會很棒。 (如果需要,我可以發佈更多的代碼)。

編輯:

下面是代碼結構的工作原理。

basePawn是一個具有一些相當基本的方法來表示字符的類。

控制器是一個帶有指向basePawn(初始設置爲NULL)的指針的類,該指針用作角色的大腦(AI或玩家控制的)。它包含一個removePawn方法。

void controller::removePawn() 
{ 
    if (pawn != NULL) 
    { 
     cout << "Calling delete.\n"; 
     delete pawn; 
     pawn = NULL; 
    } 
} 

該方法在析構函數中被調用。當棋子從關卡上移開時它也會被調用。

它也有重生方法。

if (pawn == NULL) 
{ 
    respawnCounter++; 

    if (respawnCounter >= respawnTime) 
    { 
     //Switch block to change class 
     pawn = new basePawn; 

     if (pawn !=NULL) 
     { 
      pawn->boardY = 4; //Will be random 
      pawn->boardX = 5; //Will be random 

      respawnCounter = 0; 

      pawn->setIdle(); 

      return true; 
     } 
    } 
} 

編輯:

baseController頭文件

#ifndef _BASEPAWNCONTROLLER_H 
#define _BASEPAWNCONTROLLER_H 

#include "basePawn.h" 
#include "textureManager.h" 
#include "direction.h" 
#include "vector2f.h" 

//Used to control pawns 
//Allows the same commands to be used to control different pawns 
class basePawnController 
{ 
private: 
protected: 
basePawn *pawn; 

int respawnCounter, 
    respawnTime; 

vector2f targetDest; 

bool  bMoving, 
      bTarget; 

void  removePawn(); 

public: 

bool bFirstFrameDead; 

basePawnController(); 
virtual ~basePawnController(); 

virtual void update(); 

basePawn *getPawn(); 
void setPawn(basePawn *p); 
void setTarget(float x, float y); 
direction getDir(); 
bool isMoving(); 
bool hasTarget(); 

virtual bool respawn(); 
virtual void render(textureManager &tManager); 

virtual bool wantsPawn(); 
virtual void giveTargetInfo(direction d, int n); 
}; 

#endif 
+0

你是如何分配/分配給'pawn'的?如果它是'pawn = new basePawn();',它不應該崩潰。'pawn =&some_object;'另一方面不會使它成爲'delete'的合適操作數。 – 2013-04-29 17:14:22

+1

你能給我們一個最小的完整例子嗎? – Beta 2013-04-29 17:21:11

+0

是pawn和basePawn的實現並進行一些清理的析構函數,如果它們是,你是否讓basePawn的析構函數變爲虛擬的? – 2013-04-29 17:23:09

回答

0

那麼,你們是非常正確的。

在添加了複製構造函數和賦值運算符之後,我執行了更多檢查以查看問題實際發生的位置。原來,這與我的控制器類沒有直接關係,而是我的典當和世界類。

我的兵有一個damageNode *矢量,我沒有刪除。不是一個大問題,因爲我在世界上有一個指向他們的指針。但是我從來沒有在世界級別中刪除他們,因此我在移除棋子和世界時遇到了seg錯誤。

1

由於它是PS2,我會假設你有C++ 11,並沒有打開 - 智能指針( std::unique_ptr和排序)等。如果Boost或C++ 11不是一個選項,你應該花時間學習如何重新實現基本的智能指針功能 - 這將大大緩解精神壓力。但是,讓我們假設這不是一個選項。

請注意,由於從問題和評論中收集到的問題的描述很少,這是最可能出現的情況。

您試圖通過在控制器實例超出範圍時釋放像pawn一樣的資源來使用RAII,因爲您在析構函數中調用了removePawn - 這很好。然而,當你不提供非平凡的複製賦值操作符和拷貝構造器實現以及指針和堆分配時,一個類的實例可能會丟失數據/炸掉很多方法。

你應該真正實現額外的功能來管理可能以你不期望的方式發生的複製。如果你自己不管理它,代碼可能會運行幾次,並通過將控制器傳遞給一個函數或類似的東西來讓控制器以某種方式被複制 - 它將用舊數據構造一個新的控制器。但是它是一個淺拷貝,我們假定有效的basePawn的地址將被複制,但它不會將即將死亡的實例的地址設置爲0/NULL

舊的超出範圍後,其析構函數被調用。既然你沒有使舊的指針無效,它將刪除現在由兩個不同的對象引用的相同的典當。而當你在一段時間之後說出delete pawn;時 - 繁榮。

您需要這兩個正確實施:

basePawnController(basePawnController& that); 
basePawnController& operator=(basePawnController& that); 

不要進入它聲明爲const的陷阱,是不是當你與原始指針玩耍的選項。需要採取什麼沿着這行,你可以在其他方面實現一個:

// Copy constructor 
basePawnController::basePawnController(basePawnController& rhs) { 

    *this = rhs; // invokes basePawnController::operator=() 

} 

// Copy assignment operator 
basePawnController& basePawnController::operator=(basePawnController& rhs) { 

    // copy your stuff and now the basePawn 
    pawn = rhs.pawn; // Copy the address... 
    rhs.pawn = 0; // ...but make sure the old instance doesn't troll you. 

    return *this; 

} 

我最好給你的建議是利用RAII設施進行調查,通過智能指針所有權的透明度。編程應該是一種樂趣。

+0

不幸的是,我不能使用C++ 11或Boost(事實上,編譯器和庫太舊了,它不允許使用stl :: vector的.at()方法!) 我將添加您建議的這個功能。但是,控制器類從不用作指針,只能用作實際變量。 removePawn也可以通過更新函數的中途通過分支調用(如果棋子已經死了)。如果我願意,我可以交換basePawn類型。 – 2013-04-29 21:21:53

+0

注意,我有兩個子類(一個用於playerController和一個用於AIcontroller)都是儘可能相似地實現的,邏輯流程沒有真正的變化。然而,人工智能專門在刪除呼叫上重複失敗。玩家之一非常好。 – 2013-04-29 21:22:26

+0

@ user1309389我已經在'controller'類中實現了這些方法以及它的子類中的等價物,但是這並沒有解決問題。更多信息在問題的頂部。 – 2013-04-30 09:05:12