删除指针

C++ Deleting pointer

本文关键字:指针 删除      更新时间:2023-10-16

我正在编写一个程序,它使用指针和非指向项的结构体,我正在尝试正确地释放我的数据以减少开销(这真的很重要)。

这是我有的。我实际上是在创建自己的具有特定功能的队列。我的结构体只是保存一段泛型数据和指向下一个点的指针引用。

template<class T>
struct Spot
{
    T data;
    Spot *spotBehind;
};

当我添加一个新元素时,我使用以下代码(我跟踪队列的头部和尾部)。

if(front == NULL)           //Make first head
    {
        Spot<T> *newSpot = new Spot<T>();
        newSpot->data = newElement;
        newSpot->spotBehind = front;
        front = newSpot;
        back = front;
    }
    else        //Find back of line and add
    {
        Spot<T> *newSpot = new Spot<T>();
        newSpot->data = newElement;
        newSpot->spotBehind = NULL;
        back->spotBehind = newSpot;
        back = newSpot;
    }
因此,在此之后,当涉及到析构函数时,当然我需要对每个new都有一个delete。所以析构函数使用的代码是:
Spot<T> *current = front;
Spot<T> *next = NULL;
while(current != NULL)
{
    next = current->spotBehind;
    delete current;
    current = NULL;
    current = next;
}

现在我关心的是这里。当我使用析构函数时,我认为它没有做它应该做的事情,并且这里可能存在内存泄漏。通过各种cout语句,我可以验证我的信息是否被存储并正常工作。但是当我删除数据时,它实际上并没有被删除。为了调试它,我用下面的代码替换了上面的重构器代码,以了解它在做什么。

while(current != NULL)
{
    next = current->spotBehind;
    cout << "Before Delete " << current << " Data: " << current->data << endl;
    delete current;
    cout << "After Delete " << current << " Data: " << current->data << endl;
    current = NULL;
    cout << "After Null " << current << endl;
    current = next;
    if(current != NULL)
        cout << "After Reassigned " << current << " Data: " << current->data << endl;
}

,我得到以下结果:

Before Delete 0x100103b20 Data: 5
After Delete 0x100103b20 Data: 5
After Null 0x0
After Reassigned 0x100103b30 Data: 10
Before Delete 0x100103b30 Data: 10
After Delete 0x100103b30 Data: 10
After Null 0x0

所以大问题

所以我的大问题是,信息实际上是按照它应该的方式被释放的吗?我认为我做错了什么,因为在我使用"删除"命令在我的点指针,我仍然可以看到值(也是spotBehind指针)之后。如果它按照我想要的方式工作,我不应该看到一个垃圾值和一个空的spotBehind指针,或者只是无法访问数据吗?我会很感激有人向我解释这一点,如果我这样做不正确,有人能建议一种正确删除信息的方法吗?

我认为你的代码工作正常。

表示数据在删除后仍然存在是可以的,因为删除并不意味着必须覆盖它。Delete只告诉内存管理,指针指向的内存将不再被使用,可以重新分配。在该操作之后访问它是非法的,可能会导致未定义的行为,但大多数情况下是可能的,而不会发生任何访问冲突,因为该地址仍然指向应用程序堆。

内存分配通常使用一种链表来实现。Free操作标志着该块对系统可用。一般来说,释放的内存将如何处理取决于编译器和构建类型-您是否在调试或发布中打印这些值?

例如,MS编译器在调试模式下用

填充释放的块
memset(pHead, _bDeadLandFill,  // 0xdddddddd

这里的0xdddddddd是编译器用来标记已释放内存的特殊值。

并且试图打印已删除指针的数据导致Access violation错误。您可以尝试调试operator delete,看看它是如何在您的系统中实现的。