堆栈展开后的指针有效性

时间:2011-04-25 09:06:03

标签: c++ pointers stack stack-unwinding

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

5 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

没有。使用堆栈展开在堆栈的未受损部分的作用域中声明的所有变量/指针都将被销毁。

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

当函数返回并发生堆栈展开时,在函数内的堆栈上创建的

Local variablesAuto storage type)将始终被销毁。

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

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

答案 2 :(得分:1)

这取决于指针指向的内容。如果它指向堆内存,它仍然有效。如果它指向堆栈内存,它将变为无效。

答案 3 :(得分:1)

考虑一些例子:

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丢失)。

答案 4 :(得分:0)

只是说出一件我认为重要的额外事情

说我们有这个陈述

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

如果此处发生异常.. 内存堆被重新传回....即没有内存泄漏......

原因是....  不是因为堆栈展开...而是因为new运算符转换为以下生成代码的方式 try catch语句在new运算符中实现......类似这样......

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

}
}

但是如果在对象内部进行了一些内存分配仍然没有被释放..