搜尋

首頁  >  問答  >  主體

C++模板类调用析构函数时发生异常

我是大二的学生,在做数据结构课设。用模板类写了一个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();

基本可以确定问题就出在这个部分。读完文件之后,对于读文件时创建的列表无法调用析构函数。

黄舟黄舟2768 天前615

全部回覆(3)我來回復

  • 大家讲道理

    大家讲道理2017-04-17 13:18:07

    delete單一T型態元素的記憶體應該是不需要方括號的,只有在delete一個陣列時用方括號

    回覆
    0
  • 黄舟

    黄舟2017-04-17 13:18:07

    你讀取檔案建立鍊錶使用
    reinterpret_cast(&e), sizeof(T))
    但是string根據不同實現,會導致你的passenger類實例大小不一致,這樣就都進來的數據都是亂的

    回覆
    0
  • 怪我咯

    怪我咯2017-04-17 13:18:07

    請檢查是否對同一指標做過兩次delete,或對未申請記憶體的指標做了delete;

    深淺拷貝不熟悉確實會造成這種結果,所以請重點檢查是否有兩個指針指向同一內存空間,尤其是在函數內的局部對象,在函數執行結束會自動調用局部對象的析構函數,如果這裡有局部物件的指標指向函數外空間的話,這部分空間會被釋放掉,再次存取或釋放都是不合法的。

    回覆
    0
  • 取消回覆