VS C++ 报错:BLOCK_TYPE_IS_VALID(pHead-」nBlockUse) 原因分析 及 解决方案

VS C++ 报错:BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 原因分析 及 解决方案

VS C++ 报错:BLOCK_TYPE_IS_VALID(pHead-」nBlockUse) 原因分析 及 解决方案_第1张图片

原因分析

  1. 释放已经释放了的指针
  2. delete 和 new 不配对
  3. 自定义类没有实复制构造和重载operator=

解决方案

1. 释放了已经释放的指针

案例代码一:

void test()
{
	int a = 12;
	int * b = &a;
	delete b;
}

其中,a变量是分配在栈空间的临时变量,而delete是用来释放在堆空间申请的内存,在test函数结束时,临时变量会进行销毁,而又进行了delete,导致异常
这种异常的发生,主要是在通过函数传参时,不正确的释放指针导致

案例代码二:

class Game
{
protected:
	int * data;
public:
	Game()
	{
		data = new int[10];
	}
	void clear()
	{
		delete[] data;
	}
	virtual ~Game()
	{
		clear();
		delete[] data;
	}
};
void testErr()
{
	Game game;
}

这是情况二,重复释放指针,这也是比较常见的一种错误,在类设计中经常会犯,这种问题的解决也很简单,就是先判空在释放,并且释放之后赋空

if(data!=NULL)
{
	delete[] data;
	data=NULL;
}

2. delete 和 new 不配对

案例代码,注意已经做了判空,自己要实验的话记得自己也做判空:

void testErr()
{
	Game * game=new Game[10];
	delete game;
}

如上,在分配空间时使用new[] 分配空间,而在释放时使用delete释放,这就会导致出现异常
那么,你可能会问,为什么这样的代码就不会出现异常:

int * a=new int[10];
delete a;

注意了,因为这里分配的是简单变量,我们的基本变量,这个时候是没有问题的,可以完成释放,但是一旦分配的是复合变量的时候,将会出现问题

3. 自定义的类没有实现复制构造和重载operator=

案例代码:

class Game
{
protected:
	int * data;
public:
	Game()
	{
		data = new int[10];
	}
	void clear()
	{
		if (data != NULL)
		{
			delete[] data;
			data = NULL;
		}
		
	}
	virtual ~Game()
	{
		clear();
		if (data != NULL)
		{
			delete[] data;
			data = NULL;
		}
	}
};
void testErr()
{
	Game * game=new Game[10];
	Game pg;
	game[2] = pg;
	delete[] game;
}

如上,Game类是没有实现复制构造和operator=的重写的,因此就算看起来一切正常,但是在你的pg临时变量析构的时候,将会导致重复释放,原因是Game类中的data成员是new出来的,系统默认提供的复制构造执行了浅拷贝,也就是说相当于共用内存,pg临时变量自动释放时和delete[]执行时,重复释放了同一块内存。
解决方案也很简单,就是实现复制构造和operator=,主要是实现operator=

	//实现复制构造,由于构造时没有申请空间,因此需要先申请
	Game(const Game & gm)
	{
		data = new int[10];
		for (auto i = 0; i < 10; i++)
			data[i] = gm.data[i];
	}
	//这种赋值运算符的重载写法也是比较推荐的,由于赋值时空间已经申请,
	//并且给的案例代码中,空间大小是一样的,因此不用重新申请
	Game & operator=(const Game & gm)
	{
		for (auto i = 0; i < 10; i++)
			data[i] = gm.data[i];
		return *this;
	}

复制构造可以不用实现,但是都实现operator=了,就顺便实现了吧,毕竟代码很相似,可以做如下的拆分:

Game(const Game & gm)
{
	allocMem();
	copyMem(gm);
}
Game & operator=(const Game & gm)
{
	copyMem(gm);
	return *this;
}
void allocMem()
{
	if(data==NULL)
	{
		data=new int[10];
	}
}
void copyMem(const Game & gm)
{
	for (auto i = 0; i < 10; i++)
		data[i] = gm.data[i];
}

你可能感兴趣的:(C++,开发学习)