删除这些指针时出错

时间:2017-10-02 01:44:14

标签: c++ pointers

我知道当我使用new初始化指针时,我需要删除指针或发生内存泄漏。我有一个这样设置的课程:

class foobar
{
private:

    //! Pointer to the global nodal list
    int *p_test1;

    //! Pointer to the global block label list
    int *p_test2;

public:
    foobar(int *test1, int *test2)
    {
        p_test1 = test1;
        p_test2 = test2;
    }

    ~foobar()
    {
        delete p_test1;
        delete p_test2;
    }
};

现在,当调用析构函数时,程序崩溃,控制台显示程序已退出,返回码为-6。

调试窗口指出:

程序接收信号SIGABRT

当我通过调用堆栈时,最后一项是析构函数。堆栈似乎试图释放内存但失败了。

我想知道为什么会这样?使用类设置释放内存的首选方法是什么。

作为旁注,如果我在析构函数中注释掉代码,那么当foobar类的实例完成时,指针当然不会被释放。但是,当我调用该类的另一个实例时(假设用户按下GUI上的按钮来指定实例的创建),则程序崩溃。再次,这是为什么?我觉得这与没有正确销毁指针有关。

1 个答案:

答案 0 :(得分:2)

正如评论中所提到的,此示例中没有新内容,因此很难解释newdelete之间的平衡。

规则是如果你新建了一个指针,你应该删除它。

int * p = new int( 5 );

std::cout << "The value of p is " << *p << std::endl;

delete p;

但是,如果您使用某个对象,因为您没有使用该对象,则不应该(通常)将其删除。

void somefunction( int * p )
{
    std::cout << "The value of p is " << *p << std::endl;

    delete p; // this looks smelly - deleting a pointer which was allocated.
}

为了尝试简化这个问题(我应该删除哪些指针),现代C ++有一些很好的指导。

资源获取是初始化

RAII将资源投入课堂。完整的类(与指针相对)具有非常清晰的生命周期。当它因为超出范围而被销毁时,则会调用析构函数。

 class PointerHolder {
      int * mp;
   public:
      PointerHolder( int value ) : mp( NULL) {
          mp = new int( value );
      }
      ~PointerHolder() {
          delete mp;
      }
 }

虽然上面的例子打破了5的规则。

规则5(或零)

上面的PointerHolder问题是它没有实现所有5个特殊运算符。

PointerHolder a( 12 );
PointerHolder b( 10 );

a = b;  // What is going to happen?????

a获取b指针的值,当第二个被销毁时,它是同一块内存的第二次删除,程序崩溃。

5个州的规则,如果您实施destructormove operatorcopy constructoroperator =您应该实施(或删除所有这些)

在这种情况下,删除移动和复制操作符会产生一个简单的unique_ptr

零规则是,如果一个类实现了所有运算符,或者没有一个运算符,那么它就更可重用。

如果您只需要实施某些运营商,很可能您尚未确定&#34;资源&#34; - 应该是一个包含所有5个重载运算符的单个类。

Modern C ++

从C ++ 11开始,使用new和delete,被认为仅限于库编写者。由于使用std::shared_ptrstd::unique_ptr为您管理new delete生命周期,因此您可以专注于手头的问题。