2013-06-06 22 views
2

我寫了一個很小的可觀察的的實現。當一個觀察者註冊時,它刪除舊的觀察者並使新的觀察者進入。但是,即使它沒有被初始化,它也會嘗試刪除指針。代碼如下:「如果(指針)刪除ponter」即使在指針未初始化時也要刪除

Observable.h

class Observable 
{ 
public: 
    Observable(); 
    virtual void registerObserver(Observer * O); 
    virtual ~Observable(); 

protected: 
    Observer * myObserver; 
}; 

Observable.cpp

#include "Observable.h" 

Observable::Observable() 
{ 
} 


Observable::~Observable() 
{ 
    if(myObserver) 
     delete myObserver; 
} 

void Observable::registerObserver(Observer * O) 
{ 
    if(myObserver) 
     delete myObserver; 
    myObserver=O; 
} 

所有主確實是

GUI * gui = new GUI();  // GUI extends Observer 
Model * m = new Model(); //Model extends Observable 
m->registerObserver(gui); //I get a segfault inside this call 

如果我通過registerObserver步驟,我看到即使我從來沒有初始化myObserver,聲明如果(myObserver)評估爲true。這導致未初始化的指針被刪除並出現seg錯誤。

值得注意的是,如果我運行發佈版本,我不會收到段錯誤。我只在調試版本中出現錯誤。

我的印象是,如果(myObserver)只評估爲如果指針是完整的。 (即初始化和未刪除)。

+1

由於其他原因,您正在收到段錯誤。 **已經** **做了一個'nullptr'檢查。 'if(ptr)delete ptr'與'delete ptr'完全相同。 – Yuushi

+0

右鍵:未初始化與初始化爲0不一樣。該測試從不需要。 –

回答

4

您未在代碼中初始化myObserver,因此它的初始值是不可知的。你需要明確初始化:

Observable::Observable() : myObserver(nullptr) 
{ 
} 
1

沒錯。你從來沒有初始化它,所以它的價值是undefined。這意味着你不知道它可能包含什麼值,因爲沒有設置值。它當然不能保證爲NULL。

你應該總是初始化你的指針。通常的方法是在構造函數中使用初始化列表語法來執行此操作:

Observable::Observable() 
    : myObserver(NULL) 
{ } 
1

默認情況下,C++成員變量未初始化。這意味着您的示例中您的myObserver變量不能被依賴爲0

您需要在您的構造函數中添加一個初始化來擺脫未定義行爲的狀態。

0

你需要

Observable::Observable() : myObserver(0) 
{ 
} 

!mypointer將評估爲true只有mypointer等於0(NULLnullptr等),但你明確地設置在此之前,它只是未定義 - 一些隨機值。

6

其他人已經解釋了爲什麼由於未初始化的指針而導致分段錯誤,以及如何解決這個問題。您還有其他錯誤等待發生,因爲您沒有遵循rule of three。如果您複製Observable類,則兩個實例現在都將包含myObserver的副本,並且兩者都將嘗試在各自的析構函數中指向delete,導致未定義的行爲並可能導致崩潰。

更好的實現方法是遵循rule of zero而不是自己管理指針。

#include <memory> 

class Observable 
{ 
public: 
    Observable(); 
    virtual void registerObserver(std::unique_ptr<Observer> O); 
    virtual ~Observable(); 

protected: 
    std::unique_ptr<Observer> myObserver; 
}; 

Observable::Observable() 
// no need to initialize pointer 
{} 

Observable::~Observable() 
{ 
    // no need to delete pointer manually 
} 

void Observable::registerObserver(std::unique_ptr<Observer> O) 
{ 
    myObserver.reset(O.release()); 
}