执行析构函数时造成的野指针
当执行析构函数时,使用指针往往不注意会造成野指针,那是因为,产生匿名对象时,系统所提供的赋值构造函数只是执行简单的操作,特别是涉及到动态内存方面的操作,往往需要我们手工写赋值构造函数来避免这种弊端。例如执行下面的函数就会崩溃:
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” 也可能会造成野指针,他不是系统自带赋值函数引起,但是只是执行简单的赋值,一旦释放内存,指针就会成为野指针,这点跟上面所讲类似。