2

我写了一个非常小的Observable实现。当观察者注册时,它会删除旧的观察者并设置新的观察者。但是,即使指针尚未初始化,它也会尝试删除指针。代码如下:

可观察的.h

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

protected:
    Observer * myObserver;
};

可观察的.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,语句if(myObserver)的计算结果为true。这会导致未初始化的指针被删除和段错误。

值得注意的是,如果我运行发布版本,我不会遇到段错误。我只在调试版本中得到错误。

我的印象是if(myObserver)只有在指针完好无损的情况下才会评估为真。(即已初始化且未删除)。

4

5 回答 5

6

其他人已经解释了为什么由于指针未初始化而导致分段错误,以及如何解决该问题。您还有其他错误等待发生,因为您没有遵循三规则。如果您制作Observable类的副本,则两个实例现在都将包含 的副本myObserver,并且都将尝试delete在各自的析构函数中指向指针,从而导致未定义的行为,并可能导致崩溃。

更好的实现是遵循零规则,而不是自己管理指针。

#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() );
}
于 2013-06-06T02:10:45.487 回答
4

您没有myObserver在代码中进行初始化,因此它的初始值是不可知的。您需要显式初始化它:

Observable::Observable() : myObserver(nullptr)
{
}
于 2013-06-06T02:02:01.110 回答
1

这是正确的。你从未初始化它,所以它的值是undefined。这意味着您不知道它可能包含什么值,因为从未设置任何值。它当然不能保证为 NULL。

您应该始终初始化您的指针。通常的方法是在构造函数中使用初始化列表语法:

Observable::Observable()
    : myObserver(NULL)
{ }
于 2013-06-06T02:01:52.917 回答
1

默认情况下不初始化 C++ 成员变量。这意味着在您的示例中myObserver不能依赖您的变量。0

您需要在构造函数中添加初始化以摆脱未定义行为的状态。

于 2013-06-06T02:01:54.673 回答
0

你需要

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

!mypointermypointer仅当等于 0(NULL,nullptr等)时才会评估为 true但在您明确设置之前,它只是未定义的 - 一些随机值。

于 2013-06-06T02:02:05.043 回答