【发布时间】:2011-04-25 09:06:03
【问题描述】:
在 C++ 中,指针在堆栈展开后是否仍然有效?
【问题讨论】:
-
你的意思是存储在堆栈上的指针,但指向堆,还是你的意思是你指向的东西在堆栈的一部分现在被展开?
标签: c++ pointers stack stack-unwinding
在 C++ 中,指针在堆栈展开后是否仍然有效?
【问题讨论】:
标签: c++ pointers stack stack-unwinding
这取决于指向对象的存储。如果该对象是堆栈分配的,那么指针肯定会变得无效 - 堆栈展开将正确地破坏该对象。如果对象是堆分配的,则只有在堆栈展开期间存在一些释放对象的 RAII 变量时,指针才会变为无效。
【讨论】:
这取决于你的指针指向什么。如果它指向堆内存,它仍然有效。如果它指向堆栈内存,它将变得无效。
【讨论】:
没有。随着堆栈展开,在堆栈的未展开部分范围内声明的所有变量/指针都会被销毁。
此外,该规则还考虑了变量的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
如果这里发生异常.. 内存堆被释放回来......即没有内存泄漏......
原因是…… 不是因为堆栈展开...而是因为 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
}
}
但是,如果在对象内完成了一些内存分配,但仍然没有被释放..
【讨论】: