【问题标题】:"if(pointer) delete ponter" trys to delete even when pointer is not initialized [duplicate]即使指针未初始化,“如果(指针)删除指针”也会尝试删除[重复]
【发布时间】:2013-06-01 21:35:10
【问题描述】:

我写了一个非常小的 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。这会导致未初始化的指针被删除和段错误。

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

我的印象是,如果指针完好无损,if(myObserver) 只会评估为 true。 (即已初始化且未删除)。

【问题讨论】:

  • 由于其他原因,您遇到了段错误。 delete已经执行nullptr检查。 if(ptr) delete ptrdelete ptr 完全相同。
  • 对:未初始化不等于初始化为0。这个测试从来没有必要。

标签: c++ qt pointers segmentation-fault


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        你需要

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

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

        【讨论】:

          【解决方案5】:

          其他人已经解释了为什么由于指针未初始化而导致分段错误,以及如何解决该问题。您还有其他错误等待发生,因为您没有关注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() );
          }
          

          【讨论】:

            猜你喜欢
            • 2012-04-22
            • 1970-01-01
            • 2011-12-21
            • 1970-01-01
            • 2010-09-08
            • 2013-02-11
            • 2015-08-09
            • 2012-08-05
            • 2011-07-21
            相关资源
            最近更新 更多