为什么这个删除仍导致运行时异常,即使我在删除后将指针设置为NULL

时间:2016-10-27 10:44:16

标签: c++ debugging memory-management copy delete-operator

// CplusTest20161027.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


#include <iostream>

using namespace std;

class Line {
public:
    int getLength(void);
    Line(int len);             // simple constructor
                               // Line( const Line &obj);  // copy constructor
    ~Line();                     // destructor

private:
    int *ptr;
};

// Member functions definitions including constructor
Line::Line(int len) {
    cout << "Normal constructor allocating ptr" << endl;

    // allocate memory for the pointer;
    ptr = new int;
    *ptr = len;
}

//Line::Line(const Line &obj) {
//   cout << "Copy constructor allocating ptr." << endl;
//   ptr = new int;
//   *ptr = *obj.ptr; // copy the value
//}

Line::~Line(void) {
    cout << "Freeing memory!" << endl;
    if (ptr)
    {
        delete ptr;
        ptr = NULL;
    }
}

int Line::getLength(void) {
    return *ptr;
}

void display(Line obj) {
    cout << "Length of line : " << obj.getLength() << endl;
}

// Main function for the program
int main() {
    Line line(10);

    display(line);

    return 0;
}

在上面的代码中,我评论了复制结构来测试发生了什么。我发现指针会被删除两次,所以它是一个例外。     所以我决定通过在删除后设置prt = NULL来检查是否应该删除指针。     但是,ptr将删除TWICE。为什么?     有人可以向我解释这个逻辑吗? 请帮我弄清楚出了什么问题? 输出是: 普通构造函数分配ptr 线长:10 释放记忆! 释放记忆!

堆上有例外。

1 个答案:

答案 0 :(得分:2)

我认为问题是您将Line对象按值传递给display函数:

void display(Line obj) {

然后在通话网站:

Line line(10);
display(line);

这会使line副本默认副本构造函数将执行{{>成员明智的副本{{ 1}}&#39;成员,即其Line指针。

因此,有两个析构函数调用:一个用于原始int* ptr对象,另一个用于复制,并且您获得双重破坏。

第一个析构函数调用会正确删除最初分配的堆内存 但是第二个析构函数调用尝试删除在上一次调用中已经删除的内存。

您应该禁止复制,或为line类实现正确的复制语义。

要禁止复制,您可以对复制构造函数和复制赋值Line使用C ++ 11 =delete语法,例如:

operator=

如果您禁止复制,您仍然可以传递class Line { public: ... // Ban copy Line(const Line&) = delete; Line& operator=(const Line&) = delete; }; 个对象,例如通过Line到函数:

const&

<强> P.S。
void display(Line const& obj) { delete(代码中的nullptr的现代C ++ 11版本)指针一样正常,因此您不需要冗余NULL在致电if (ptr)之前检查。