我正在尝试用C++实现一个链表。链表包含一个指向堆上分配的节点类型的指针
代码如下:
#include <memory>
template<typename T>
class node {
public:
node(T v) : value(v) {}
~node() = default;
T value;
node *next;
};
template<typename T, class Allocator = std::allocator<node<T>>>
class linked_list {
private:
node<T>* head;
Allocator alloc;
public:
linked_list() : head(nullptr) {}
~linked_list() {
for (auto start = head; start != nullptr; start = start->next) {
start->~node();
alloc.deallocate(start, 1);
}
}
void push_back(T value) {
node<T> *new_node = alloc.allocate(1);
new (new_node) node<T>(value);
if (head == nullptr) {
head = new_node;
return;
}
head->next = new_node;
head = new_node;
}
};
在main.cpp中:
#include "linked_list.hpp"
int main() {
linked_list<int> a;
a.push_back(4);
a.push_back(5);
return 0;
}
当我运行它的时候,我在缓存T2中检测到了双重释放。我在析构函数上做错了什么?
1条答案
按热度按时间7d7tgy0s1#
这是新手常见的错误。您修改了循环控制变量。
您修改了for循环体中的
start
(删除内存),然后试图取消引用刚刚在其延续表达式中删除的指针。BOOM!您很幸运,运行时库足够聪明,能够捕捉到这一点,并给予您“双重释放”错误,而不是发射核导弹。这是while循环优于for循环的一个地方。
我省略了很多关于你的过时技术的评论,因为它们与你所遇到的问题无关,但是如果你真的想用一种不同的分配器来代替,你应该考虑使用
allocator_traits
来分配、构造、销毁和释放你的元素。还有其他一些问题,比如
push_back
在插入新节点的位置上完全错误。用new_node->next = head;
替换head->next = new_node;
至少可以防止程序孤立所有的新节点。