C++析构函数造成Debug Assertion Failed的问题

 

昨天写了两个程序,均出现了析构函数造成Debug Assertion Failed的问题,由于是初学c++怎么想也想不通问题出在哪里。今天早上经人指点终于明白问题所在了。下面贴出代码和问题解析:(以下内容摘自本人在csdn论坛求助的帖子)

 

第一个问题程序:
//Teacher_Level.h

#pragma once
#include<iostream>
using namespace std;
int num=0;
class Teacher
{
public:
char *title;

Teacher()
{
title=new char[50];
}

~Teacher()
{
cout<<"called:"<<++num<<endl;
if(title!=NULL)
{
delete[] title;
title=NULL;
}
}

};

class Level
{
public:
char *position;

Level()
{
position=new char[50];
}

~Level()
{
if(position!=NULL)
{
delete[] position;
position=NULL;
}
}
};


class Teacher_Level:public Teacher,public Level
{
public:
void show()
{
cout<<"The teacher_level:"<<endl;
cout<<"Title:";
puts(title);
cout<<"Position:";
puts(position);
}
};

//main.cpp

#include "Teacher_Level.h"
#include<iostream>
using namespace std;

int main()
{
Teacher_Level p;
p.title="professor";
p.position="header";
p.show();

return 0;
}

报错如下:



第二个问题程序:
//CShop.h

#pragma once
#include<string.h>
#include<iostream>
using namespace std;

class CShop
{
public:
char *product;
int price;

CShop();
CShop(char *CProduct,int CPrice);
~CShop();

friend ostream& operator<<(ostream& os,CShop p)
{
cout<<"Product:";
puts(p.product);
cout<<"Price:";
cout<<p.price;

return os;
}

};

CShop::CShop()
{
product=new char[50];
}

CShop::CShop(char *CProduct,int CPrice)
{
product=new char[50];
strcpy(product,CProduct);
price=CPrice;
}

CShop::~CShop()
{
if(product!=NULL)
{
delete[] product;
product=NULL;
}
}


//main.cpp

#include "CShop.h"
#include<iostream>
using namespace std;

int main()
{
char *product="book";
int price=120;
CShop p(product,price);
cout<<"The information of the shop:"<<endl;
cout<<p<<endl;

return 0;
}

报错如下:

 

 

正确解答:

第一个:
Teacher_Level p;  // 这里调用了构造函数,给title分配了内存
p.title="professor";  // 这里又直接把title指向了常量区,导致析构函数里面企图delete一个常量区指针
应该照着第二个程序的思路来给title赋值。

 

第二个程序的问题稍微有点复杂。
friend ostream& operator<<(ostream& os,CShop p)
这里的p是按值传递的,编译器要调用拷贝构造函数来创建一个新对象。但是你自己没写拷贝构造函数,所以编译器自己生成了一个拷贝构造函数,问题由此产生,因为编译器的拷贝构造函数是所谓“浅拷贝”,简单的复制了product的地址。然后销毁这个新对象的时候就把product的地址delete了。你可能会说,delete之后把product赋值NULL了,但那是针对那个临时对象的,main里面的p的product指针没有变动,还指向最初的new的结果,然后退出main的时候就再次delete,导致出错。
把这个<<重载函数的参数改成&p可以绕过这个问题,但是根本的解决方法是自己写一个拷贝构造函数,不是简单的复制指针,而是重新new一个指针然后strcpy。

 

对于这两个程序的问题,我收获很大,特别是第二个让我理解了拷贝构造函数的调用机制。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。