即使指针未初始化,"if(pointer) delete ponter"也会尝试删除

"if(pointer) delete ponter" trys to delete even when pointer is not initialized

本文关键字:ponter delete 删除 指针 初始化 if pointer      更新时间:2023-10-16

我写了一个非常小的 observable 实现。当一个观察者被注册时,它会删除旧的观察者并创建新的观察者。然而,它试图删除指针,即使它没有被初始化。代码如下:

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。这将导致未初始化的指针被删除和segfault。

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

我的印象是if(myObserver)只有在指针完整的情况下才会求值为true。(即初始化未删除)

其他人已经解释了为什么由于未初始化的指针而导致分割错误,以及如何解决这个问题。你仍然有其他错误等待发生,因为你没有遵循三原则。如果你复制了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() );
}

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

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

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

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

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

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

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

你需要

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

!mypointer只有在mypointer等于0 (NULL, nullptr等)时才会计算为true,但在显式设置此值之前,它只是未定义—一些随机值。