堆栈展开后的指针有效性

Pointer validity after stack unwinding

本文关键字:指针 有效性 堆栈      更新时间:2023-10-16

在c++中,堆栈展开后指针是否仍然有效?

这取决于指向对象的存储。如果该对象是堆栈分配的,那么指针肯定是无效的——堆栈展开将正确地销毁该对象。如果对象是堆分配的,只有当在堆栈展开期间有一些RAII变量释放对象时,指针才会失效。

这取决于你的指针指向什么。如果它指向堆内存,它仍然有效。如果它指向堆栈内存,它就无效。

No。通过堆栈展开,在堆栈未损坏部分的作用域中声明的所有变量/指针将被销毁。

此外,该规则还考虑了变量的Storage Type
static变量在函数调用之间保持其值,这意味着它在堆栈展开期间不会被销毁。这是因为静态变量不是存储在堆栈中,而是存储在BSS或数据段中。

在函数内部的堆栈上创建的

Local variables (Auto storage type)总是在函数返回和堆栈展开时被销毁。

在堆上分配内存的指针在堆栈展开时不会被销毁,因为它们是在堆上而不是堆栈上分配的。

要记住的一个重要规则是永远不要返回指向函数内部局部变量的指针或引用。指针或引用将包含垃圾值。

考虑一些例子:

void* f1a()
{
    void* p = malloc(10);
    return p;
}

void* f1b()
{
    return malloc(10);
}

这很好,因为指针指向堆,因此独立于堆栈、函数调用和编程作用域。在函数返回时复制指针值。

int* f2()
{
    int x;
    return &x;  // pointer to x - about to become invalid!
}

上面的函数返回一个指向堆栈上的变量x的指针,当函数返回时,该指针将被回收(x丢失)。

再说明一件我觉得很重要的事

说我们有这个语句

obj* objptr = new obj(9) //allocate memory on heap and use constructor

if here exception发生…内存堆被释放回....没有内存泄漏…

原因是....不是因为堆栈展开…而是因为new操作符转换为下面生成的代码的方式try catch语句在new operator中实现…像这样…

void * operator new(size_t s)
{
try
{
void * ptr=new(malloc (s))sample(); //placement new
ptr->...
}
catch(..)
{
operator delete(ptr);   //<= notice here   so if an exception occur then first it         is caught here which releases the memory
}
}

然而,如果在对象内做了一些内存分配,仍然没有被释放。