我对 C/C++ 中的悬空指针有点困惑
void remove(){
Node* curr = new Node(10);
Node* pt = curr;
delete curr;
// do something here
// do other thing here
}
我假设在函数终止Node* pt
之前仍然是悬空指针?remove()
我不必担心终止Node* pt
后的指针?remove()
我对 C/C++ 中的悬空指针有点困惑
void remove(){
Node* curr = new Node(10);
Node* pt = curr;
delete curr;
// do something here
// do other thing here
}
我假设在函数终止Node* pt
之前仍然是悬空指针?remove()
我不必担心终止Node* pt
后的指针?remove()
你的问题似乎是基于一个错误的假设,即有一个悬空指针有问题。它绝对没有任何问题,尝试设置所有悬空指针NULL
等是一种反模式。只是不要取消引用悬空指针。
在 的注释部分中remove
,buthcurr
和pt
是悬空指针,因为它们都指向已删除的对象。只要该代码不取消引用它们,就没有问题。
调用时delete curr
,其中存储的值curr
不变,但该位置的内存已返回给系统。
让我们逐行遍历您的代码:
Node* curr = new Node(10);
为了论证的缘故,让我们假设分配的内存地址为 0x1000,这意味着curr
现在的值为0x1000
.
Node* pt = curr;
pt 现在也有值(指向位置)0x1000。
delete curr;
这会将位置 0x1000 的内存返回给系统。curr
但是,此时两者pt
都包含值 0x1000。
它们都是悬空指针。
当你使用原始指针时,悬空指针是不可避免的,而且它们并不是隐含的坏。您只需要注意不要使用悬空指针或返回一个。
void badfunc() {
char* p = new char[10];
delete p;
return p; // use of dangling pointer
}
关于您的问题:“我假设 Node* pt 在函数 remove() 终止之前仍然纠缠指针?”
是的,在调用之前由两者指向delete curr;
的内存块后,会被释放。调用后你不应该使用既不使用也不使用值(它们都有相同的值,并且它是无效的)。不要假设调用改变了 的值。它没有 - 您可以通过在调用之前和之后打印两个值来检查它,如下所示:Node* curr
Node* pt
curr
pt
delete curr;
delete
curr
delete curr;
printf("%d, %d", curr, pt);
关于您的问题:“我不必担心 remove() 终止后的指针 Node* pt 吗? ”
确实,在remove()
完成两者Node* curr
之后Node* pt
不再存在。它们也超出了remove()
. 因此,您不必担心它们。
此外,存储在内存中的对象/数据先前指向并被Node* curr
释放Node* pt
/破坏delete curr;
,因此您也不必担心它。
有时建议通过将悬空指针设置为 NULL 来避免悬空指针。这并不能缓解问题,但如果您不小心使用了这样的指针,它至少会清楚地表现出来。这是因为尝试取消引用 NULL 指针会导致内存分段错误 - 所以您至少会得到一个可重现的运行时错误来查找您的错误。其他人说盲目地将每个未使用的指针设置为 NULL 会使您的代码混乱。这里需要一些智慧来衡量优点和缺点。
悬空指针是指指向不再有效对象的指针。这不需要基于 new/delete 或 malloc/free:事实上,非指针可以悬空。任何对另一个对象或资源的引用,如果引用不再有效,但引用“不知道”,就可以说是“悬空”。
如果您取消引用悬空指针,则会发生未定义的行为(有时什么都没有,有时是段错误,有时您的硬盘驱动器被格式化,有时您的代码时间旅行(是的,我是认真的))。
所以不要取消引用悬空指针。
在 之后delete
,两个指针都悬空。
通常,如果您的代码强制要求变量处于您可以从它们的类型和/或名称中确定的已知状态,则有助于推理程序。一个例子可能是“没有悬空指针,在删除后立即将它们设置为 null”:然后,如果您总是在创建时将指针初始化为 null,则每个指针要么有效,要么指向 null。
使用持久数据执行此操作是一个好主意。在微小的函数中使用局部变量这样做通常会增加更多的噪音而不是帮助。
另一种方法是更喜欢使用智能指针,但它们有自己的陷阱。引用计数和标记和清除智能指针将悬空指针变成资源泄漏!并且唯一 ptr 没有安全的“观察者”指针类型。
范围结束后的本地指针不复存在。它不能是悬空指针,因为它不是指针。