删除整数指针时析构函数末尾的分段错误

segmentation fault at the end of the destructor on deleting integer pointer

本文关键字:分段 错误 析构函数 整数 指针 删除      更新时间:2023-10-16

我正在尝试理解以下程序。执行时出现错误,如下所示。

#include<iostream>
using namespace std;
class Base
{
public:
    int *a;
    int a1;
    int b;

    Base(){
        cout<<"Inside Constructor"<<endl;
        a1 = 10;
        a = &a1;
        cout<<"   "<<a<<endl;
        b = 20;
    }
    Base(const Base &rhs)
    {
        cout<<"Inside Copy Constructor"<<endl;
        a = new int;
        *a = *(rhs.a);
        b = rhs.b;
    }
    ~Base(void)
    {
    cout<<"Inside destructor"<<endl;
    delete a;
    }
};

int main()
{
Base obj;
Base obj2(obj);
cout<<"obj a "<<*(obj.a)<<" b "<<obj.b<<endl;
cout<<"obj2 a "<<*(obj2.a)<<" b "<<obj2.b<<endl;
obj.a1 = 30;
obj.b = 40;
cout<<"obj a "<<*(obj.a)<<" b "<<obj.b<<endl;
cout<<"obj2 a "<<*(obj2.a)<<" b "<<obj2.b<<endl;
return 0;
}

执行此代码时,我得到以下输出

Inside Constructor
Inside Copy Constructor
obj a 10 b 20
obj2 a 10 b 20
obj a 30 b 40
obj2 a 10 b 20
Inside destructor
Inside destructor
Segmentation fault

[编辑]我正在寻找一种方法来破坏我在复制构造函数中创建的堆内存。那么这里能做什么呢?请建议

[编辑]

删除应该只使用new在堆分配的内存上使用。

a1 = 10;
a = &a1;

在您的情况下,"a"将内存地址保存在堆栈中。因此,您不应该在该内存上调用 delete。

您必须删除使用 new(动态分配)获取的内存,而不是自动存储变量。

在复制构造函数中,您正在使用 new 运算符为指针 a 分配内存,以便您可以删除它。但由于您没有在默认构造函数中使用 new 运算符,因此您可以删除指针 a 。您必须使用删除操作器来释放堆中而不是堆栈中的变量的内存。

当您使用 new 运算符时,变量是在中创建的,其中作为局部变量是在堆栈内存中创建的,无法使用删除运算符删除

问题不在于复制构造函数,问题在于您没有始终如一地使用new(如果您使用 move,那么也许您会有道理)。你有一些选择。我试图变得有用,而不是详尽无遗,也许我错过了其他好的设计理念。

始终(并始终)使用new

您可以在所有构造函数中放置一个新的,因此,析构函数将始终能够调用 delete 。即使你不需要它。这可能是一个丑陋的黑客,但始终如一。

切勿使用new

如果您从不使用new,则也不使用delete,编译器可确保一致性并确保您不会搞砸。通常,您可以依赖构造函数上的编译器默认行为。

使用智能指针

如果不是手动调用delete而是将变量保存在unique_ptr中,那么编译器将在析构函数中自动释放它。智能指针足够智能,可以知道它是否已初始化。

请注意,使用智能指针意味着您永远不应该调用delete,因为如果您在没有警告智能指针的情况下这样做,您将偶然发现同样的问题。如果您不熟悉它们并且正在使用 C++11,那么学习:)是一件好事

跟踪指针的状态

我不会保证这一点。看起来很C,不C++.但是,您始终可以跟踪bool值并在销毁时对其进行检查。这就像使用智能指针一样,但需要内部实现。我认为这是一个糟糕的设计理念,尽管在某些情况下具有教育意义。