我编写了一个双向链表(在这种情况下存储素数),我在使用列表后尝试删除的元素。我在列表的析构函数中编写了一个简单的循环。但是,我可以在删除后打印每个元素中保存的值。释放内存后,我预计会出现“错误访问”错误。此外,我使用Activity Monitor在程序执行的各个点显示正在使用的资源。创建链表时(显然)内存使用量大幅增加,但在调用析构函数后也有小幅增加。我认为有些事情是错误的。
正在为列表的每个成员调用'delete'语句,但它似乎没有做任何事情。我已经在下面的析构函数中包含了相关的代码。列表和元素使用'new'语句创建。 'current','head'和'tail'标签是指向列表元素(节点)的指针。
PrimeList::~PrimeList()
{
// delete list elements
do
{
current = tail;
tail = tail->previous;
delete current;
}
while( tail != NULL );
// nullify the pointers
head = NULL;
tail = NULL;
current = NULL;
// reset size
size = 0;
}
任何见解?
答案 0 :(得分:2)
删除对象不一定会改变对象占用的内存,更不用说让后续访问的内存不可用了。有多种方法可以确保您的程序不会访问已删除的内存,例如使用调试分配器以不常见的位模式覆盖已删除的内存,或者使用动态分析工具(如valgrind)。
答案 1 :(得分:1)
删除元素后访问元素是一个错误。当然,带有错误的代码将无法像您期望的那样工作。这就是为什么我们试图避免这样的代码。
你的析构函数看起来很好。最有可能的是,正在发生的事情是,你的析构函数内部只是让内存可以重用。由于您没有更改其内容或分配任何新对象,因此它“恰好具有”相同的内容。
答案 2 :(得分:1)
您是否通过引用将列表的头部传递给了删除方法?
否则,您只是尝试删除列表的副本,以便在您尝试访问列表时列表仍然存在。
我看不到你的整个代码,但是对于析构函数,你应该做这样的事情:
PrimeList::~PrimeList()
{
deleteList( &head); // pass the reference to the head pointer
}
void PrimeList::deleteList( struct node** headRef)
{
struct node* head = *headRef;
// now apply your deletion algorithm
}
答案 3 :(得分:1)
所有delete
所做的是使对象使用的内存可供另一个对象重用(并调用析构函数,如果有的话)。它不会擦除内存或将其标记为无法使用或其他任何内容(至少,它不能保证 - 它可能会感觉像它)。在将来某个时间内存可能被分配给另一个对象,此时它将被覆盖。
delete
内存未返回给系统,您的进程会保留该内存以供将来new
(以及malloc
,...)重用。这就是为什么Activity Monitor仍然认为你正在使用那个内存。有更好的方法可以确定您是否正确地释放了列表,搜索“c ++内存泄漏检测器”或其他类似的内容。
答案 4 :(得分:1)
您的编译器很可能是“帮助您”。在链表中实现析构函数的一种好方法是递归。假设列表中的每个条目都有一个类Node,
class Node {
public:
~Node() {delete this->next;}
};
PrimeList::~PrimeList() {
delete head;
}