我是大二的学生,在做数据结构课设。用模板类写了一个List的数据结构,存放的数据是一个自定义的class。现在的问题在于每次调用析构函数的时候都会发生异常。根据追踪,是在调用传入的自定义类的析构函数时候出现了内存无法访问的错误。
自定义类的定义如下:
class passenger
{
public:
passenger();
passenger(string ID, string name, int totalMileage);
passenger(const passenger& p);
~passenger() {};
void show();
private:
string ID;
string name;
int totalMileage;
};
ListNode定义如下:
#define ListNodePosi(T) ListNode<T>*
template <typename T>struct ListNode
{
// 成员
T data;// 数值
ListNodePosi(T) pred;// 前驱
ListNodePosi(T) succ;// 后继
// 构造函数
ListNode() {}
ListNode(T e, ListNodePosi(T) p = NULL,ListNodePosi(T) s = NULL)
: data(e), pred(p), succ(s) {}
~ListNode()
{}
// 操作接口
ListNodePosi(T) insertAsPred(T const& e);
ListNodePosi(T) insertAsSucc(T const& e);
};
List的析构函数会调用自己编写的remove函数,追踪时发现是remove这里出了问题。
template<typename T>// 此处传入我自定义的类
T List<T>::remove(ListNodePosi(T) p)
{
T e = p->data;
p->pred->succ = p->succ;
p->succ->pred = p->pred;
delete[] p;
_size--;
return e;
}
在进行delete[] p;这条语句时出现错误,继续追踪,发现是在调用自定义类的析构函数时出现了问题,提示内存无法访问。
异常的提示为:
引发了异常: 读取访问权限冲突。
std::_String_alloc<std::_String_base_types<char,std::allocator<char> >
::_Myres(...) 返回 0x77E0EB64。
但是我的自定义类中并没有用new申请新的空间,为什么会出现这样的问题?
从网上查到资料说是深拷贝浅拷贝一块的问题,于是我提供了一个复制构造函数,但是问题依旧,请问该如何解决?
谢谢!
因为我的数据是通过二进制文件读入的,经过排查之后发现是读文件之后再调用析构函数会出现这样的问题。
下面是我的读文件的代码:
template<typename T>
void List<T>::createList(ifstream &file)
{
T e;
while (file.read(reinterpret_cast<char *>(&e), sizeof(T)))
{
insertAsLast(e);
}
}
相关函数代码(List文件中):
template<typename T>
ListNodePosi(T) List<T>::insertAsLast(T const& e)
{
_size++;
return trailer->insertAsPred(e);
}
另一个相关函数(ListNode中):
template<typename T>
ListNodePosi(T) ListNode<T>::insertAsPred(T const & e)
{
ListNodePosi(T) x = new ListNode(e, pred, this);
pred->succ = x;
pred = x;
return x;
}
main函数中进行了一下测试
ifstream rpassfile("passenger.dat", ios_base::in | ios_base::binary);
List<passenger> p2;
p2.createList(rpassfile);
p2.traverseShow();
rpassfile.close();
基本可以确定问题就出在这个部分。读完文件之后,对于读文件时创建的列表无法调用析构函数。
delete单个T类型元素的内存应该是不需要方括号的,只有在delete一个数组时用方括号
你读取文件建立链表使用
reinterpret_cast<char *>(&e), sizeof(T))
但是string根据不同实现,会导致你的passenger类实例大小不一致,这样就都进来的数据都是乱的
请检查是否对同一指针做过两次delete,或对未申请内存的指针做了delete;
深浅拷贝不熟悉确实会造成这种结果,所以请重点检查是否有两个指针指向同一内存空间,尤其是在函数内的局部对象,在函数执行结束会自动调用局部对象的析构函数,如果在这里有局部对象的指针指向函数外空间的话,这部分空间会被释放掉,再次访问或释放都是不合法的。