62

我知道这是一个很常见的问题,但对我来说还是个新问题!

我不明白悬空指针的概念,正在谷歌搜索,并编写测试方法来找到一个。

我只是想知道这是一个悬空指针吗?因为我发现的任何例子都是返回一些东西,在这里我正在尝试类似的东西!

谢谢!

void foo(const std::string name)
{
    // will it be Dangling pointer?!, with comments/Answer
    // it could be if in new_foo, I store name into Global.
    // Why?! And what is safe then?
    new_foo(name.c_str());
}

void new_foo(const char* name)
{
    // print name or do something with name...   
}
4

7 回答 7

76

悬空指针是指向无效数据或不再有效数据的指针,例如:

Class *object = new Class();
Class *object2 = object;

delete object;
object = nullptr;
// now object2 points to something which is not valid anymore

即使在堆栈分配的对象中也会发生这种情况:

Object *method() {
  Object object;
  return &object;
}

Object *object2 = method();
// object2 points to an object which has been removed from stack after exiting the function

如果字符串后来被修改或销毁,则返回的指针c_str可能会变得无效。在您的示例中,您似乎没有修改它,但是由于不清楚您将要做什么,const char *name因此不可能知道您的代码本质上是否安全。

例如,如果您将指针存储在某处,然后相应的字符串被销毁,则指针将变为无效。如果您const char *name仅在范围内使用new_foo(例如,出于打印目的),则指针将保持有效。

于 2013-08-01T14:48:19.760 回答
12

悬空指针是指向未分配(已释放)内存区域的(非 NULL)指针。

上面的例子应该是正确的,因为字符串不是通过 new_foo 修改的。

于 2013-08-01T14:50:13.990 回答
10

取自这里。虽然,即使这适用于 C,但对于 C++ 也是如此。

悬空指针

当一个指针指向一个变量的内存地址,但经过一段时间后,该变量从该内存位置删除,而指针仍然指向它,那么这样的指针被称为悬空指针,这个问题被称为悬空指针问题。

最初

在此处输入图像描述

之后

在此处输入图像描述

例子

#include<stdio.h>

int *call();
int main() {

  int *ptr;
  ptr = call();

  fflush(stdin);
  printf("%d", *ptr);
  return 0;
}

int * call() {
  int x=25;
  ++x;

  return &x;
}

它的输出将是垃圾,因为该变量x是局部变量。它的作用域和生命周期都在函数调用内,因此在返回变量的地址后,x变量的地址x变成了死的,指针仍然指向那个位置。

于 2016-01-22T11:05:50.520 回答
6

作为风格问题,我将悬空指针解释为“仍然存在的指针,即使它指向的对象不再存在”。

在您的情况下,指针name存在的时间比它指向的对象的时间短。所以它永远不会悬空。

在常见的 C++ 类中,指针在析构函数中的悬挂时间很短。那是因为该delete语句}在析构函数的最后一个之前,而指针本身不再存在于最后一个}。如果您不想担心这一点,请使用 eg unique_ptr<T>。指针将T*在析构函数内悬挂很短的时间unique_ptr::~unique_ptr,这是非常安全的。

于 2013-08-02T07:49:20.077 回答
5

悬空指针是指堆栈中有有效指针但指向无效内存的情况。当您在堆栈中的指针被释放之前释放堆内存时,您可能最终会遇到这种情况。

这是一个安全问题。因为当您释放内存时,我们会通知操作系统,我们不再需要这部分内存。因此,当其他应用程序请求内存时,操作系统会将那块内存标记为准备好分配并分配给其他应用程序。

通常,在 C++ 中,通过通用模式分配和释放内存。当类初始化时调用类中的构造函数,这是在堆中分配内存的正确位置。当类实例超出范围时将调用析构函数,这是从堆中释放内存的正确位置。假设我们已经创建了一个类,分别在构造函数和析构函数中进行内存分配和释放。

int main() {
  SomeClass pointer1 = SomeClass();
  SomeClass pointer2 = pointer1;
}

在上面的示例代码中,声明了两个变量,但都具有相同的值。当构造函数被调用时,它会分配一个堆内存。然后我们再声明一个变量并分配相同的值。通常在 C++ 中,当您分配一个复杂类型的值时,它会执行浅拷贝(除非您显式实现了拷贝构造函数)而不是深拷贝。这意味着唯一的指针被复制到堆栈中,而不是堆内存。实际上出于性能原因不建议复制堆内存。现在最终的内存布局看起来像我们有两个指向同一个堆内存的指针。

现在,当函数完成执行时,局部变量会超出范围并调用析构函数。首先,pointer2 调用释放堆内存的析构函数。此时,pointer1 变成了悬空指针。它指向一个已经被释放的内存。

从这个例子中,我们了解到悬空指针的主要原因是同一资源有多个所有者。因为当一个指针释放内存时,其他指针变成了悬空指针。

于 2019-11-12T07:49:17.510 回答
1

//Declaring two pointer variables to int
int * ptr1;
int * ptr2;
// Allocating dynamic memory in the heap
ptr1 = new int;
ptr2 = ptr1; // Having both pointers to point same dynamic memory location
//deleting the dynamic memory location 
delete ptr1;
ptr1 = nullptr; 
//ptr2 is still pointing the already deleted memory location 
//We call ptr2 is a dangling pointer
于 2020-06-30T15:11:14.597 回答
-2

悬空指针和悬空指针问题 如果任何指针指向任何变量的内存地址,但在某个变量从该内存位置删除后,而指针仍指向该内存位置。

该指针称为悬空指针,此时出现的问题称为悬空指针问题。

下面是一些例子:悬空指针和悬空指针问题

于 2016-07-26T09:37:34.343 回答