0

这不是具有相似名称的问题的重复,这涉及 OOP 以及 new 和 delete 调用。

我正在尝试编写一个函数,该函数将迭代到我的链表的后面,然后删除最后一个节点堆中分配的内存。

这是我的代码:

void LinkedList::delete_back(){
    if(head != NULL){
            ListNode *end = head;
            while(end->next != NULL)
                    end = end->next;
            delete end;
    }
    size--;
}

这是我的类定义:

class ListNode{

    public:
            Item data;
            ListNode *next;
};
class LinkedList{

    private:
            ListNode *head;
            int size;

    public:
            LinkedList();
            ~LinkedList(); 
            bool empty();
            void insert_front(Item i);
            void insert_back(Item i);
            void delete_front();
            void delete_back();
            void print();
};

Andddddd .....这是问题所在,我收到来自 valgrind 的类似这样的错误消息的垃圾邮件,其中一些声明大小为 4 的无效读取,另一些声明大小为 8 的无效读取:

==4385== Invalid read of size 4
==4385==    at 0x400CAA: LinkedList::print() (in /home/jon/jball2_lab06/linkedlist)
==4385==    by 0x400EDD: main (in /home/jon/jball2_lab06/linkedlist)
==4385==  Address 0x5a04f30 is 0 bytes inside a block of size 16 free'd
==4385==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4385==    by 0x400C5E: LinkedList::delete_back() (in /home/jon/jball2_lab06/linkedlist)
==4385==    by 0x400E99: main (in /home/jon/jball2_lab06/linkedlist) 

如果有帮助,我会发布其余的错误,但除非我需要,否则我不想在 50 行上击中 4 次空格。有谁知道这可能是什么?我究竟做错了什么?

更新------------------------ 我已将代码编辑为:

void LinkedList::delete_back(){
    if(head != NULL){
            ListNode *end = head;
            ListNode *prev_end;
            while(end->next != NULL){
                    prev_end = end;
                    end = end->next;
            }
            prev_end->next = NULL;
            if(end != NULL) delete end;
            size--;
    }
}

我现在越来越多地读取大小为 8/4 的错误和无效的免费/删除错误

==5294== Invalid free() / delete / delete[] / realloc()
==5294==    at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

和这个:

==5294== Use of uninitialised value of size 8
==5294==    at 0x400C3D: LinkedList::delete_back() (in /home/jon/jball2_lab06/linkedlist)
==5294==    by 0x400EEC: main (in /home/jon/jball2_lab06/linkedlist)

这是我使用的测试代码:

    for(Item i = 50; i < 100; i++){
            ll.insert_back(i);
            cout << "Inserted [" << i << "] in back.\n";
    }
    ll.print();
    for(int i = 0; i < 50; i++)
            ll.delete_back();
    cout << "Removed 50 elements from the back.\n";
    ll.print();

当使用 delete_back() 从列表中删除最后一个元素时会发生这种情况

更新 - - - - - - - - - - - - -

问题是如果 end->next 为空,那么 while 循环将永远不会执行,prev_end 永远不会被初始化。已实施修复的发布答案。

4

6 回答 6

4

当您的列表包含至少 2 个节点并且您delete是最后一个节点时。前一个仍然具有对最后一个的引用(不再存在),这会在您尝试取消引用无效(悬空)指针时导致未定义的行为。print代替:

ListNode *end = head;
while(end->next != NULL)
    end = end->next;
delete end;

你应该做:

if (head->next == NULL) {
    delete head;
    head = NULL;
}
else {
    ListNode *nextToEnd = head;
    ListNode *end = head->next;
    while (end->next != NULL) {
        nextToEnd = end;
        end = end->next;
    }
    delete end;
    nextToEnd->next = NULL;
}
于 2013-10-11T19:50:53.413 回答
1

不要忘记更新next新的最后一个元素。

void LinkedList::delete_back(){
    if(head != NULL){
            ListNode *end = head;
            ListNode *prev_end;
            while(end->next != NULL)
            {
                 prev_end = end;
                 end = end->next;
            }
            prev_end->next = 0;
            delete end;
    }

此外,如果您清空列表,请将 head 设置为 NULL。

于 2013-10-11T19:50:33.450 回答
1

您没有将新的端节点设置为空。

例如:

A->B->C->NULL

当你删除 C 时,B 的下一个是一个悬空指针

因此,在删除函数中,您需要转到倒数第二个节点并将其 next 设置为 NULL。

在上面的示例中,删除 C 后,列表应如下所示

A->B->NULL 而不是 A->B->(悬空)

因此,您可以在下一个 delete_back 操作中删除 B。

您可以执行以下操作

void LinkedList::delete_back(){
if(head != NULL){
        ListNode *end = head;
        //This if block is for when only one element is left
        if(end->next == NULL)
         { delete end;
           end = NULL;
         }
        else
        while(end!= NULL)
        { 
               if(end->next) /// reach the second last element
                if(end->next->next==NULL)
                 {
                  delete end->next; //delete the last element
                  end->next=NULL; // set the next of second last element to NULL
                 }
               end=end->next;
        } 
  size--;
  }
  }
于 2013-10-11T20:03:01.950 回答
0

修复了所有问题。

代码:

void LinkedList::delete_back(){
    if(head != NULL){
            ListNode *end = head;
            if(end->next != NULL){
                    ListNode *prev_end;
                    while(end->next != NULL){
                            prev_end = end;
                            end = end->next;
                    }
                    prev_end->next = NULL;
                    delete end;
            }
            else {
                    delete head;
                    head = NULL;
            }
            size--;
    }
}
于 2013-10-13T19:37:35.390 回答
0

最后最容易删除的代码是:

void DeleteAtLast(){
    node *temp=head;
    while(temp->next->next!=NULL){
        temp=temp->next;
    }
    temp-next=NULL;
}
于 2016-12-06T19:31:01.540 回答
0

像这样应该可以

void del_rear()

{
  struct node *end, *last

 if (head->next != NULL) {

   *end=head;

while(end->next!=null){
*last=end;
 end=end->next;
  }
    free(end);
    last->next=null;
   }     
 else
   {

    pf("list is empty\n");
 }
} 
于 2015-10-23T15:10:44.207 回答