“if(指针)删除指针”即使未初始化指针也会尝试删除

时间:2013-06-06 02:00:26

标签: c++ qt pointers segmentation-fault

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

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,语句 if(myObserver)评估为 true 。这会导致未初始化的指针被删除并出现seg错误。

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

我认为 if(myObserver)只会在指针完好无损的情况下评估为 true 。 (即初始化但未删除)。

5 个答案:

答案 0 :(得分: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() );
}

答案 1 :(得分:4)

您没有在代码中初始化myObserver,因此它的初始值不可知。您需要明确初始化它:

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

答案 2 :(得分:1)

没错。你从来没有初始化它,所以它的值是未定义。这意味着你不知道它可能包含什么值,因为没有设置任何值。当然不能保证是NULL。

你应该总是初始化你的指针。通常的方法是使用构造函数中的initialiser-list语法执行此操作:

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

答案 3 :(得分:1)

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

您需要在构造函数中添加一个初始化,以摆脱未定义行为。

答案 4 :(得分:0)

你需要

Observable::Observable() : myObserver(0)
{
}
仅当!mypointer等于0(mypointerNULL等)时,

nullptr才会评估为真,但在您明确设置之前,它只是未定义 - 有些随机值。