C++ delete 出现断点

main


int main() {
  LinkList<int>* a = new LinkList<int>();
  for (int i = 1; i < 100; ++i)
  {
    a->Add(i);
  }
  for (int i = 0; i < a->Size(); ++i) {
    cout << a->Get(i) << endl;
  }
  
  delete a;  //在这显示:已引发异常
  a = nullptr;
}

Link


template <class T>
struct Link {
    T data;
    struct Link* next;
    struct Link* last;
};

LinkList


template <class T>
LinkList<T>::LinkList() {
  head = new Link<T>();

  head->next = head;
  head->last = head;

  count = 0;
}

template <class T>
LinkList<T>::~LinkList() {
  while (head != nullptr) {
    Link<T>* link = head->next;
    delete head;
    head = link;
  }
}


template <class T>
bool LinkList<T>::IsEmpty() const {
  return count == 0;
}

template <class T>
int LinkList<T>::Size() const {
  return count;
}

template <class T>
T& LinkList<T>::Get(const int index) const {
  Link<T>* link = head;
  for (int i =0; i<=index; ++i)
  {
    link = link->next;
  }
  return link->data;
}

template <class T>
int LinkList<T>::IndexOf(const T& element) const {
  Link<T>* link = head;
  for (int i =0; i < count ; ++i)
  {
    link = link->next;
    if ( link->data == element )
    {
      return i;
    }
  }
  link = nullptr;
  return -1;
}

template <class T>
void LinkList<T>::Erase(const int index) {
  Link<T>* link = head;
  for (int i =0; i < index; ++i)
  {
    link = link->next;
  }
  link->next->last = link->last;
  link->last->next = link->next;
  count--;
  link = nullptr;
}

template <class T>
void LinkList<T>::Add(const T& elememt) {
  Link<T>* link = new Link<T>();
  link->data = elememt;
  link->next = head;
  link->last = head->last;
  head->last->next = link;
  head->last = link;
  link = nullptr;
  count++;
}

template <class T>
void LinkList<T>::Insert(const int index, const T& element) {
  Link<T>* link = head;
  for (int i =0; i < index; ++i)
  {
    link = link->next;
  }
  Link<T>* tmp = new Link<T>();
  tmp->data = element;

  tmp->next = link;
  tmp->last = link->last;
  link->last->next = tmp;
  link->last = tmp;

  count++;
}

“去掉 delete a;就可以执行” 这种思路不是正解哈,相当于你不销毁内存,而是靠进程释放销毁内存。
你的问题不在于调用了delete a,而是在于LinkList的析构函数~LinkList写的有问题。

因为你这写的是个循环双向链表,而在析构函数种你采用delete掉head所指节点以释放内存,所以在head指向最后一个节点时,最后一个节点的next指向你第一个删除的节点地址,这块内存释放了,其值为任意随机值,但是你的判断条件为 head != nullptr,就是这里错了。

因为 nullptr 的值为 0,但head此时是一个任意值,不等于0满足,所以会走到循环中,对无效内存再进行一次delete。不信你可以printf("%x", nullptr); 看看是多少。
所以判断指针为空我们一般用另一个写法。 !head。

template <class T>
LinkList<T>::~LinkList() {
    //while (head != nullptr) {   这句错了哈
    while (!head) {
        Link<T>* link = head->next;
        delete head;
        head = link;
    }
}

你这个链表不是单向列表,所有的节点都有next,所以

LinkList<T>::~LinkList() {
  while (head != nullptr) {
    Link<T>* link = head->next;
    delete head;
    head = link;
  }

这个析构函数是错误的。你会循环删除节点,当所有节点删除后,你又会转到之初的head进行delete,但此时这个head已经给释放掉了,指针就成了野指针,释放自然会崩溃了。你最好记住这个head,当再次循环到这个head指针时,结束释放。比如

LinkList<T>::~LinkList() {
  Link<T> *p = head;
  while (head != nullptr) {
    Link<T>* link = head->next;
    if(link == p)
          break;
    delete head;
    head = link;
  }

去掉 delete a;就可以执行

main函数改一下试试:

 
int main() {
  LinkList<int> a;// = new LinkList<int>();
  for (int i = 1; i < 100; ++i)
  {
    a.Add(i);
  }
  for (int i = 0; i < a.Size(); ++i) {
    cout << a.Get(i) << endl;
  }
  //delete a;  //在这显示:已引发异常
  //a = nullptr;
}

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632