无法删除我的临时指针?

时间:2013-06-14 00:14:28

标签: c++ pointers

我在删除指针时遇到问题。我不认为我做任何编译非法或任何事情,但也许我是,所以如果有人可以解释我的逻辑中的缺陷,我将不胜感激。我希望下面的功能应该足以提供帮助,因为整个事情需要转录很多,但如果需要更多的代码,请告诉我,我会添加它!

以下是从我创建的链接列表中删除储物柜的功能。我尽力覆盖每一个可以想象的案例。当我试图实际释放我想要删除的储物柜的内存时,问题就出现了。我试图删除引用锁定的临时变量的行被注释掉了,因为包含了代码。显然,如果没有它们,我就无法删除我想要的储物柜。

int SelfStorageList::removeLockersOverdue() {

int lockersDeleted = 0;

if (isEmpty()) {
    return 0;
}

if (head->objLocker.isRentOverdue && head==tail) { //If that was the only locker, the tail needs to be updated to = head = 0
    delete head;  
    head = tail = 0;
    return ++lockersDeleted;
}

LockerNode *prev = head;
LockerNode *curr = head->next;

while (curr != 0) {

    if((curr == tail) && curr->objLocker.isRentOverdue) { //If the current locker is tail and needs deleting
        LockerNode *temp = curr;
        curr = prev;
        //delete temp;
        lockersDeleted++;
    }


    if(prev->objLocker.isRentOverdue) { //General case: Previous locker needs deleting
       LockerNode *temp = prev;
       prev = prev->next;
       curr = curr->next;
       //delete temp;
       lockersDeleted++;

   }

  else { //Update the pointers if not updated anywhere else

  prev = prev->next; 
  curr = curr->next;

  }

}

return lockersDeleted;

}

任何“指针”? (可怕的双关语:p)

2 个答案:

答案 0 :(得分:3)

因为您正在维护一个单链表,所以当您在列表中进行迭代时,我看到您正在跟踪prev指针。当然,这应该是应该的,因为如果单个链接而不记住其先前节点是什么,则无法获取链接列表中给定节点的先前节点。您的问题只是您的逻辑被破坏:如果需要删除,您需要删除curr节点,并修补prev节点以将其next指针指向{在您curr->next之前{1}}。

考虑一下:你正在做的是删除delete curr节点,但是可能还有一个“比那更早的”节点仍指向你刚删除的prev节点。下次迭代列表时,您将迭代到以前分配的节点,这些节点可能会被分配给某个完全不同的目的。你的内存分配器失败了一些内部断言,因为可能在你下次调用removeLockersOverdue()时,内存还没有被分配给其他东西,你仍然在那里找到你已经删除的那个节点,并再次找到它已经过期,并再次删除它,你的内存分配器抱怨你正在删除未分配的内存。 (如果它能让你清楚地知道一条消息,那将是非常好的,不是吗!)

此外,您的特殊情况用于处理第一个节点&最后一个节点可以简化&公共化;我会避免为你重写它,所以你可以看看你是否可以自己简化它。

答案 1 :(得分:3)

while (curr != 0) {
    if((curr == tail) && curr->objLocker.isRentOverdue) {
        LockerNode *temp = curr;
        curr = prev;
        //delete temp;
        lockersDeleted++;
    }

您没有在此处更新上一个节点的下一个指针,因此它最终悬空(指向已删除的内存)。您还将tail指向已删除的节点。

    if(prev->objLocker.isRentOverdue) {
       LockerNode *temp = prev;
       prev = prev->next;
       curr = curr->next;
       //delete temp;
       lockersDeleted++;

   }

同样,您不会更新列表中指向已删除节点的next指针。

  else { //Update the pointers if not updated anywhere else

  prev = prev->next; 
  curr = curr->next;

  }
}

我认为通过在循环中携带两个指针,你会非常困惑自己。尝试使用单个指针跟踪您当前正在检查的节点再次编写它,并绘制三种可能情况的一些图片(删除第一个节点,删除最后一个节点,删除内部节点)以确保您正确获取删除逻辑。