执行析构函数时造成的野指针


当执行析构函数时,使用指针往往不注意会造成野指针,那是因为,产生匿名对象时,系统所提供的赋值构造函数只是执行简单的操作,特别是涉及到动态内存方面的操作,往往需要我们手工写赋值构造函数来避免这种弊端。例如执行下面的函数就会崩溃:
class Name
{
public:
	Name(const char *myp)
	{
		int len = strlen(myp);
		p = (char *)malloc(len+1);
		strcpy(p,myp);
	}
	~Name()
	{
		if (p != NULL)
		{
			free(p);
			p = NULL;
			len = 0;
		}
	}
protected:
private:
	char *p;
	int len;
};
void objplaymain()
{
	Name obj1("adcd");
	Name obj2 = obj1;//会自行调用系统提供的赋值构造函数,产生匿名对象
}
void main()
{
	objplaymain();
	
	return;
}

  当执行  strcpy(p,myp); 时,系统只是把myp的地址做了个拷贝,p并没有创建新的内存,其本质和myp的地址一样指向了同一块内存,

  当执行完 void objplaymain()此函数后,会执行析构函数,析构的顺序是先执行后释放,当obj2对象先析构后,p和myp共同指向的内存被释放,而obj1对象后析构,但其内存被释放,从而产生野指针,后果是系统会崩溃。解决方法是给obj2也创建一个内存空间:

class Name
{
public:
	Name(const char *myp)
	{
		len = strlen(myp);
		p = (char *)malloc(len+1);
		strcpy(p,myp);
	}
      Name(const Name& obj)
    {
       len = obj1.len;
        p = (char *)malloc(len +1);
       strcpy(p,obj1.myp);
    } 
	~Name()
	{
		if (p != NULL)
		{
			free(p);
			p = NULL;
			len = 0;
		}
	}
protected:
private:
	char *p;
	int len;
};
void objplaymain()
{
	Name obj1("adcd");
	Name obj2 = obj1;//会自行调用系统提供的赋值构造函数,产生匿名对象
}
void main()
{
	objplaymain();
	
	return;
}

  应当注意的是,对象的赋值操作如“obj2=obj1” 也可能会造成野指针,他不是系统自带赋值函数引起,但是只是执行简单的赋值,一旦释放内存,指针就会成为野指针,这点跟上面所讲类似。