在什么情况下 delete 运算符会抛出错误?
In what context does the delete operator throw an error?
在我的链表实现中,删除内部 class Node
实例的辅助函数 deleteNode(Node*)
抛出运行时错误,由 "triggering a breakpoint" 在VS 2015 中的本地 Windows 调试器。我很小心地匹配我的 new
和 delete
运算符。 scope/reference 是否起到了我没有意识到的作用?
即使clear()
出现逻辑错误,deleteNode()
通过nullptr
,删除nullptr
也不应该抛错,然后赋值nullptr
对自己好吗?该删除有什么问题?
class LinkedList {
public:
LinkedList() : head(nullptr) {}
~LinkedList() { clear(); }
void push_front() {
head = createNode(head);
}
void clear() {
Node* current_node = head;
while (current_node != nullptr) {
Node* next_node = current_node->next; // buffer
deleteNode(current_node);
current_node = next_node;
}
}
private:
struct Node {
Node(Node* next)
: next(next) {}
Node* next;
};
Node* head;
Node* createNode(Node* next) {
return new Node(next);
}
void deleteNode(Node*& toDelete) {
delete toDelete; // ***VS 2015 puts breakpoint here***
toDelete = nullptr;
}
};
int main() {
auto A = LinkedList();
A.push_front();
A.clear();
return 0;
}
我删除了所有与错误无关的属性和方法。这个伪代码仍然抛出同样的错误。
In what context does the delete operator throw an error?
一个delete
表达式可以抛出,如果析构函数本身抛出,或者一个子对象的析构函数。但是你应该避免使用析构函数。
如果您尝试删除未指向有效对象的指针,delete
表达式也可能具有未定义的行为。 nullptr
是一个例外,可以安全删除。意外删除无效指针的典型原因是试图删除相同的指针值两次,或者忘记初始化内存。未定义的行为可能导致任何结果,包括抛出错误。
What is the issue with that delete?
您正在删除同一个指针两次。您可以通过检查调试器中的值来验证这一点。
问题出在您的 clear()
函数中。你看,你 认为 由于你编写 deleteNode
函数的方式,你所有的节点都将 nullptr
在 clear
之后。不幸的是,事实并非如此。您将 head
复制到 current_node
,并且 head 的副本(即 current_node)在被删除时变成 nullptr
,但 head
保持非空.稍后析构函数尝试再次删除它。在已释放的内存上调用 delete 会导致未定义的行为。
要修复,请添加
head = nullptr;
在你清除函数的最后
在我的链表实现中,删除内部 class Node
实例的辅助函数 deleteNode(Node*)
抛出运行时错误,由 "triggering a breakpoint" 在VS 2015 中的本地 Windows 调试器。我很小心地匹配我的 new
和 delete
运算符。 scope/reference 是否起到了我没有意识到的作用?
即使clear()
出现逻辑错误,deleteNode()
通过nullptr
,删除nullptr
也不应该抛错,然后赋值nullptr
对自己好吗?该删除有什么问题?
class LinkedList {
public:
LinkedList() : head(nullptr) {}
~LinkedList() { clear(); }
void push_front() {
head = createNode(head);
}
void clear() {
Node* current_node = head;
while (current_node != nullptr) {
Node* next_node = current_node->next; // buffer
deleteNode(current_node);
current_node = next_node;
}
}
private:
struct Node {
Node(Node* next)
: next(next) {}
Node* next;
};
Node* head;
Node* createNode(Node* next) {
return new Node(next);
}
void deleteNode(Node*& toDelete) {
delete toDelete; // ***VS 2015 puts breakpoint here***
toDelete = nullptr;
}
};
int main() {
auto A = LinkedList();
A.push_front();
A.clear();
return 0;
}
我删除了所有与错误无关的属性和方法。这个伪代码仍然抛出同样的错误。
In what context does the delete operator throw an error?
一个delete
表达式可以抛出,如果析构函数本身抛出,或者一个子对象的析构函数。但是你应该避免使用析构函数。
如果您尝试删除未指向有效对象的指针,delete
表达式也可能具有未定义的行为。 nullptr
是一个例外,可以安全删除。意外删除无效指针的典型原因是试图删除相同的指针值两次,或者忘记初始化内存。未定义的行为可能导致任何结果,包括抛出错误。
What is the issue with that delete?
您正在删除同一个指针两次。您可以通过检查调试器中的值来验证这一点。
问题出在您的 clear()
函数中。你看,你 认为 由于你编写 deleteNode
函数的方式,你所有的节点都将 nullptr
在 clear
之后。不幸的是,事实并非如此。您将 head
复制到 current_node
,并且 head 的副本(即 current_node)在被删除时变成 nullptr
,但 head
保持非空.稍后析构函数尝试再次删除它。在已释放的内存上调用 delete 会导致未定义的行为。
要修复,请添加
head = nullptr;
在你清除函数的最后