cod*_*her 43 c++ pointers dangling-pointer
我知道这是很常见的问题,但对我来说还是新的!
我不明白悬挂指针的概念,谷歌搜索,并编写测试方法找到一个.
我只是想知道这是一个悬垂的指针吗?无论我发现什么样的东西都回来了,我在这里尝试类似的东西!
谢谢!
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...
}
Run Code Online (Sandbox Code Playgroud)
Jac*_*ack 55
悬空指针是指向无效数据或指向无效数据的指针,例如:
Class *object = new Class();
Class *object2 = object;
delete object;
object = nullptr;
// now object2 points to something which is not valid anymore
Run Code Online (Sandbox Code Playgroud)
即使在堆栈分配的对象中也会发生这种情
Object *method() {
Object object;
return &object;
}
Object *object2 = method();
// object2 points to an object which has been removed from stack after exiting the function
Run Code Online (Sandbox Code Playgroud)
c_str如果字符串之后被修改或被销毁,则返回的指针可能变为无效.在你的例子中,你似乎没有对它进行修改,但由于不清楚你将要做什么,const char *name因此不可能知道你的代码本质上是否安全.
例如,如果将指针存储在某处,然后销毁相应的字符串,则指针变为无效.如果const char *name仅在范围内使用new_foo(例如,出于打印目的),则指针将保持有效.
取自这里。虽然,即使这是针对 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;
}
Run Code Online (Sandbox Code Playgroud)
它的输出将是垃圾,因为该变量x是一个局部变量。它的范围和生命周期在函数调用中,因此在返回x变量的地址后,它x变成死的,指针仍然指向那个位置。
悬空指针是指堆栈中存在有效指针,但指向无效内存的情况。当您在释放堆栈中的指针之前释放堆内存时,您可能会遇到这种情况。

这是一个安全问题。因为当您释放内存时,我们正在通知操作系统,我们不再需要这部分内存。因此操作系统会将该块内存标记为准备分配,并在其他应用程序请求内存时分配给它们。
通常,在 C++ 中,通过通用模式分配和释放内存。当类初始化时,会调用类中的构造函数,这是在堆中分配内存的正确位置。当类实例超出范围时,将调用析构函数,这是从堆中释放内存的正确位置。假设我们已经创建了一个类,它分别在构造函数和析构函数中分配和释放内存。
int main() {
SomeClass pointer1 = SomeClass();
SomeClass pointer2 = pointer1;
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例代码中,声明了两个变量,但它们都具有相同的值。当构造函数被调用时,它会分配一块堆内存。然后我们声明另一个变量并分配相同的值。在 C++ 中,通常,当您分配复杂类型的值时,它会执行浅复制(除非您显式实现复制构造函数)而不是深复制。这意味着唯一的指针被复制到堆栈中,而不是堆内存中。实际上出于性能原因不建议复制堆内存。现在,最终的内存布局看起来像我们有两个指针指向同一堆内存。

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

从这个例子中,我们了解到悬空指针的主要原因是同一资源有多个所有者。因为当一个指针释放内存时,其他指针就变成了悬空指针。
作为一种风格,我将悬空指针解释为“一个仍然存在的指针,即使它指向的对象不再存在”。
在您的情况下,指针name存在的时间比它指向的对象要短。所以它永远不会悬空。
在常见的 C++ 类中,指针会在很短的时间内在析构函数中悬空。那是因为该delete语句}在析构函数的最后一个之前,而指针本身在最后一个}. 如果您不想担心这一点,请使用 eg unique_ptr<T>。该T*指针将吊着的内部很短的时间unique_ptr::~unique_ptr析构函数,这是完全安全的。