分割故障(核心转储)当我删除指针
我试图从链表中删除重复项,并遇到了一个问题,这可能是显而易见的,直接的,但我没有在多年使用C++
,但是我做不到通过阅读SO上的类似问题来了解我做错了什么。分割故障(核心转储)当我删除指针
下面是我的代码部分。我删除了不相关的部分(例如构造函数,其他方法等)。
template<class T>
class Node {
Node() : data(NULL), next(NULL), prev(NULL) {}
explicit Node(T d) : data(d), next(NULL), prev(NULL) {}
explicit Node(T d, Node<T> *nxt, Node<T> *prv) : data(d), next(nxt), prev(prv) {}
~Node() { delete next; delete prev; }
T data;
Node *next;
Node *prev;
};
template<class T>
class LinkedList {
LinkedList() : head(NULL) {}
explicit LinkedList(Node<T> *head_node) : head(head_node) {}
LinkedList& operator=(const LinkedList ©_list);
~LinkedList(); //didn't implement this but I guess delete head is all?
Node<T>* head;
};
template<class T>
LinkedList<T> RemoveDuplicates(const LinkedList<T> &linked_list) {
//my = overload creates a whole new list with the same data as the original one
LinkedList<T> result = linked_list;
Node<T> *cur = result.head;
Node<T> *prev = NULL;
while (cur) {
if (...) { //duplicate found
Node<T> *temp = cur;
prev->next = cur->next;
cur = cur->next;
cur->prev = prev;
free(temp); //Here is my problem!!!
}
else {
prev = cur;
cur = cur->next;
}
}
return result;
}
所以第一,我没有delete temp
和我Segmentation fault
。然后我意识到你只有delete
你new
什么。不够公平,但我new
荷兰国际集团各Node
建设main
整个列表时:
Node<char> *h = new Node<char>('H'); //I have a constructor to handle this
Node<char> *e = new Node<char>('E');
Node<char> *l1 = new Node<char>('L');
Node<char> *l2 = new Node<char>('L');
Node<char> *o = new Node<char>('O');
h->next = e;
h->prev = NULL;
e->next = l1;
e->prev = h;
//and so on
那么,为什么我不能delete
东西,是new
版别的地方?是否因为在当前范围之外是new
?
二,free
ing的空间工作正常,但显然不是正确的事情,因为我没有malloc
但new
ed!
我在做什么错?如何正确杀死删除的节点?
EDIT1地:它根据回复我的帖子 更具描述性EDIT2:3种方法规则添加
这是正确识别和解决OP的即时问题的其他答案的附录。为了解释接下来会发生什么,需要快速解决问题。
Node<T> *temp = cur;
prev->next = cur->next;
cur = cur->next;
cur->prev = prev;
此时温度尚未清除,所以next和prev仍然指向用于环绕CUR和现在连接在一起的两个节点。如果不是因为这会造成严重的问题:因为该值指向临时被新分配
free(temp); //Here is my problem!!!
free
失败。 NathanOliver的回答有这个覆盖,但潜伏的下方是将
delete temp;
这发生将调用析构函数清理是一个不错的小东西是什么。不幸的是,Node
析构函数看起来是这样的:
~Node() { delete next; delete prev; }
temp->next
仍然指向一个活动节点。 temp->prev
也是如此。
下一步和prev获得delete
d。其中调用它们的析构函数,delete
它们触摸的两个节点,并调用一个将破坏列表中的所有节点的死亡风暴。
如果双删除不首先杀死程序。每个链接节点都会尝试delete
这个节点,它们只是deleted
。不好。
几率很好,Node
析构函数应该照顾自己,并将其他Node
s的破坏保留到LinkedList
类。
不能使用free()
如果用new
分配的内存,您可以使用malloc()
与free()
或new
与delete
。你也应该不使用malloc()
和free()
使用对象,因为他们不调用对象的构造函数和析构函数不像new
和delete
那么既然你用new
分配的节点,我们可以改变
free(temp); //Here is my problem!!!
到
delete temp;
当我做'删除临时文件'时,我得到'Segmentation fault' – Yalda
,那么你在代码中的某个地方有问题。请提供一个[mcve] – NathanOliver
@Yalda [规则三](http://*.com/questions/4172722/what-is-the-rule-of-ree)最可能的问题。 –
在这种情况下,具有构造函数的代码,同时也析构函数是非常重要的。
默认情况下,你应该在构造函数中使用的“新”,并在析构函数“删除”。更具体地说,分配构造函数中所需的所有资源并在析构函数中释放资源非常重要,这样可以确保您没有任何内存泄漏。
free(temp);//You don't need this, also you don't need delete.
请发布您的构造函数和析构函数代码。
L.E:
我认为你应该做这样的事情:
template<class T>
class LinkedList
{
private:
struct Node {
T m_data;
Node *m_next;
Node *m_prev;
};
Node* m_first;
Node* m_last;
int m_count;
public:
LinkedList();
~LinkedList();
T GetFirst();
T GetLast();
void AddNode(T node);
void RemoveAt(int index);
T GetAt(int index);
int Count();
};
//constructor
template <typename T>
LinkedList<T>::LinkedList(){
m_count = -1;//-1 == "The list is empty!
}
template <typename T>
void LinkedList<T>::AddNode(T data){
Node* temp = new Node; //new is called only here -> delete is called in destructor or in RemoveAt
temp->m_data = data;
if (m_count > -1){//If the list contains one or more items
temp->m_next = m_first;
temp->m_prev = m_last;
m_last->m_next = temp;
m_last = temp;
m_count++;
}
else if (m_count == -1)
{//If no items are present in the list
m_first = temp;
m_first->m_next = temp;
m_first->m_prev = temp;
m_last = temp;
m_last->m_next = temp;
m_last->m_prev = temp;
m_count = 0;
}
}
template <typename T>
void LinkedList<T>::RemoveAt(int index){
if (index <= m_count)//verify this request is valid
{
Node* temp = m_last;
for (int i = 0; i <= index; ++i){
temp = temp->m_next;
}
temp->m_prev->m_next = temp->m_next;
temp->m_next->m_prev = temp->m_prev;
delete temp;
m_count--;
}
}
template <typename T>
T LinkedList<T>::GetAt(int index)
{
Node* temp = m_first;
if (index <= m_count && index > -1){
int i = 0;
while(i < index){
temp = temp->m_next;
i++;
}
}
return temp->m_data;
}
template <typename T>
T LinkedList<T>::GetFirst() {
return m_first->data;
}
template <typename T>
T LinkedList<T>::GetLast(){
return m_last->data;
}
template <typename T>
int LinkedList<T>::Count(){
return m_count;
}
template <typename T>
LinkedList<T>::~LinkedList(){
while(m_count > -1){
Node* temp = m_first;
m_first = temp->m_next;
delete temp;//delete in destructor
m_count--;
}
}
那么,为什么我不可以删除的东西,是newed地方 别的吗?是因为它在当前范围之外被新出现吗?
您被允许登录delete
new
东西在其他地方编辑。只要你指向一个有效的地址,这不是一个问题。当您尝试使用指向now- delete
ed地址的指针之一时,会出现seg-fault。
其次,释放空间工作正常,但我觉得这就像作弊!
,才应使用free
当你使用malloc
和delete
当你使用new
。你应该从来没有混合起来。此外,在delete
之后,养成将NULL
分配给指针变量的习惯。
因为我可能需要在我的Node的析构函数上完成的事情。
封装数据的类还应该在内部执行自己的内存管理。例如,LinkedList
应该管理节点的内存。
这意味着,如果你有类似LinkedList<T>::add(Node<T> *data)
的东西,你应该改为像LinkedList<T>::add(T data)
;那么列表类本身负责处理节点。
否则,您可能会冒险将new
ed节点发送到列表中,然后列表delete
在某个时间点内部发生,但是在其他地方,列表的客户端仍持有对现在无效节点的引用。当客户端尝试使用它时,再次使用bam!:seg-fault。
我在做什么错?如何正确杀死删除的节点?
除了new
s的free
小号混合,该段错误很可能是由一个无效的内存访问触发,所以你会发现,不再指向有效的(即未deleted
)内存的指针。
有很多答案,指出new/delete
和malloc()/free()
应始终如此配对,但我认为它应该确切的说为什么。
在你的初始化,
Node<char> *h = new Node<char>('H');
的new
关键词返回一个完全类型的对象对象的指针,在语句本身定义的,而malloc()
只是分配一个指定的存储空间而不指定类型,所以返回void*
。此外,new/delete
处理免费商店中的内存,而malloc()/free()
在堆上分配/释放内存,尽管在某些情况下,某些编译器可能根据malloc()/free
实施new/free
。
而且一些重要的是new
和delete
调用构造函数和析构函数分别,而malloc()
和free()
简单地分配和释放堆内存,而不考虑内存本身的状态。
[可能有用。](http://*.com/q/33047452/472647) – CodeMouse92
'〜Node(){delete next;删除prev; }'会杀死它周围的节点。例如,您可以从节点X和Z之间删除节点Y,将X和Z链接起来。然后'删除Y'来获取它的资源。 Y的析构函数将破坏X和Z.X和Z的析构函数将破坏他们所触及的所有元素,包括正在被破坏的X和Z.这是我们过去称为非常糟糕的场景。如果我是你,我会重新考虑析构逻辑。 – user4581301