Administrator
Administrator
发布于 2025-08-31 / 21 阅读
0
0

类实例双重释放导致的崩溃

如:将类实例通过值传递给函数,在函数退出作用域时会调用析构函数,在调用者退出时会再次析构

错误代码

#include <iostream>

using namespace std;

class custom_class
{
public:
	int* i;
	short s{0};
	custom_class() = default;
	~custom_class()
	{
		cout << "析构 s=" << s << endl;
		delete[] i;
	}

	custom_class(const custom_class &old) //拷贝构造函数
	{
		i = old.i;
		s = old.s + 10;
		cout << "call copy constructor" << endl;
	}
};

void func(custom_class c)
{
	cout << "func, c.i=" << c.i << ", c.s = " << c.s << "\n";
}

int main()
{
	custom_class c1;
	c1.i = new int[3] {1, 2, 3};
	c1.s = 10;

	func(c1); //这里在传参时也会调用拷贝构造函数,函数内的形参变量c是浅拷贝的对象


	//此时c1也将自动调用析构函数,但是c1.i和func函数形参c.i是相同的指针,c.i已经在func退出作用域时释放了
	//c1.i成为了野指针(悬空指针),所以调用析构函数时程序会崩溃
	return 0;
}

解决方法1

//传引用
void func(custom_class &c)
{
	cout << "func, c.i=" << c.i << ", c.s = " << c.s << "\n";
}

func(c1);
//传指针
void func(custom_class *c)
{
	cout << "func, c.i=" << c->i << ", c.s = " << c->s << "\n";
}

func(&c1);

解决方法2

在析构时,将指针设置为nullptr,释放空指针不会有问题

class custom_class
{
public:
	int* i;
	short s{0};
	custom_class() = default;
	~custom_class()
	{
		cout << "析构 s=" << s << endl;
		delete[] i;
        i = nullptr;
	}

	custom_class(const custom_class &old) //拷贝构造函数
	{
		i = old.i;
		s = old.s + 10;
		cout << "call copy constructor" << endl;
	}
};


评论