澄清C/C++中的悬空指针问题

3

我对C/C++中的悬空指针感到有些困惑。

void remove(){
Node* curr = new Node(10);
Node* pt = curr;
delete curr;

// do something here
// do other thing here
}

我假设在函数remove()终止之前,Node* pt仍然是悬空指针?

remove()终止后,我不必担心指针Node* pt


1
pt 是此函数的本地变量;在控制流程离开函数后,您不必担心它。 - Beta
1
没有叫做C/C++的语言。我将删除C标签,因为这显然是一个C++问题。 - fuz
4个回答

9
你的问题似乎是基于错误假设,认为悬空指针有问题。其实悬空指针并没有任何问题,将所有悬空指针设置为NULL等是一种反模式。只要不对悬空指针进行解引用操作即可。
remove的注释部分,currpt都是悬空指针,因为它们都指向已被删除的对象。只要这段代码没有对它们进行解引用操作,就不会出现问题。

2
您的问题似乎基于错误假设,即拥有悬空指针是有问题的。喜欢它。+1 - skypjack
1
这就是我来SO寻求澄清的原因,这就是SO的用途吧? - 1234

5

当你调用 delete curr 时,存储在 curr 中的值不会改变,但是该位置的内存已经被返回给系统。

让我们逐行分析你的代码:

Node* curr = new Node(10);

为了举例说明,假设分配的内存地址为0x1000,这意味着curr现在的值为0x1000

Node* pt = curr;

现在,pt的值(指向位置)为0x1000。

delete curr;

这将返回位于0x1000地址的内存给系统。但是,此时currpt仍然都包含值0x1000。

它们都是悬空指针。

当您使用原始指针时,悬空指针是不可避免的,并且它们并不是隐式的坏事。您只需要小心不要使用悬空指针或返回悬空指针即可。

void badfunc() {
    char* p = new char[10];
    delete p;
    return p;  // use of dangling pointer
}

3
  1. 关于你的问题:"我假设在函数remove()终止之前Node* pt仍然是悬挂指针?"
    是的,在调用delete curr;后,原先由Node* currNode* pt指向的内存块被释放。在调用delete curr;之后不应该再使用curr或者pt的值(它们都有相同的值,并且无效)。不要假设调用delete会改变curr的值。它不会——你可以像这样在调用delete curr;之前和之后打印出两个值来检查:

    printf("%d, %d", curr, pt);

  2. 关于你的问题:"在remove()终止后,我不必担心指针Node* pt吗?"
    确实如此,在remove()完成后,Node* currNode* pt都不存在了。它们也超出了作用域(在remove()之外不可访问)。因此,你不必担心它们。

  3. 此外,delete curr;释放/销毁了先前由Node* currNode* pt指向的内存中的对象/数据,因此你也不必担心它。

  4. 有时候建议通过将悬挂指针设置为NULL来避免它们。这并不能解决问题,但如果你不小心使用这样的指针,它至少会清晰地表示出来。这是因为尝试取消引用NULL指针会导致内存分段错误——所以你至少可以得到一个可重现的运行时错误来查找你的错误。其他人说,盲目地将每个未使用的指针设置为NULL会使你的代码混乱不堪。在这里需要一些智慧来权衡利弊。


0
悬空指针是指指向不再有效的对象的指针。这不一定是基于new/delete或malloc/free的:实际上,非指针也可能会悬空。任何对另一个对象或资源的引用,其中引用不再有效,但引用“不知道”,都可以被称为“悬空”。
如果您解除引用悬空指针,则会发生未定义行为(有时什么也不会发生,有时会出现段错误,有时会格式化硬盘,有时代码会时间旅行(是的,我很认真))。
因此,请勿解除引用悬空指针。
在delete之后,两个指针都是悬空的。
通常,如果您的代码强制要求变量处于已知状态,您可以从其类型和/或名称确定该状态,这可以帮助推理程序。一个例子可能是“不要有悬空指针,在删除后立即将它们设置为null”:然后,如果您始终在创建时将指针初始化为null,则每个指针都是有效的或指向null。
对于持久数据来说,这样做是一个好主意;但对于小函数中的局部变量来说,这样做通常会增加更多的噪音而不是帮助。

另一种方法是优先使用智能指针,但它们也有自己的陷阱。引用计数和标记-清除智能指针会将悬空指针转换为资源泄漏!而unique ptr没有安全的“观察者”指针类型。

局部指针在其作用域结束后就不存在了。它不能成为悬空指针,因为它不是指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接