Joh*_*Doe 23 c++ callstack exception-handling exception
在下面的代码中,基于堆栈的变量"ex"被抛出并被捕获到超出声明ex的范围的函数中.这对我来说有点奇怪,因为(AFAIK)基于堆栈的变量不能在它们被声明的范围之外使用(堆栈被展开).
void f() {
SomeKindOfException ex(...);
throw ex;
}
void g() {
try {
f();
} catch (SomeKindOfException& ex) {
//Handling code...
}
}
Run Code Online (Sandbox Code Playgroud)
我已经向SomeKindOfException的析构函数添加了一个print语句,它显示ex在f()中超出范围后被破坏但是它在g()中被捕获并且一旦它超出范围就再次被破坏.
有帮助吗?
Joh*_*itb 10
该对象被复制到一个异常对象中,该对象在堆栈展开后仍然存在.该对象的内存来自何处未指定.对于大对象,它可能是malloc
'ed,对于较小的对象,实现可能有一个预分配的缓冲区(我可以想象这可以用于bad_alloc
异常).
ex
然后将引用绑定到该异常对象,该对象是临时的(它没有名称).
Kir*_*sky 10
C++标准15.1/4:
除非在3.7.3.1中指出,否则将以未指定的方式分配要抛出的异常的临时副本的内存.只要存在针对该异常执行的处理程序,临时就会持续存在.特别是,如果处理程序通过执行throw而退出; 语句,将控制权传递给另一个处理程序以获得相同的异常,因此临时保留.当为异常执行的最后一个处理程序以throw以外的任何方式退出时; 临时对象被销毁,实现可能会释放临时对象的内存; 任何这种解除分配都是以未指明的方式完成的.在销毁处理程序中的exception-declaration中声明的对象后立即发生破坏.
没有什么可说的了.
当您抛出ex时,它将被复制到用于抛出异常对象的特殊内存位置.这种拷贝由普通拷贝构造器执行.
您可以通过此示例轻松查看此内容:
#include <iostream>
void ThrowIt();
class TestException
{
public:
TestException()
{
std::cerr<<this<<" - inside default constructor"<<std::endl;
}
TestException(const TestException & Right)
{
(void)Right;
std::cerr<<this<<" - inside copy constructor"<<std::endl;
}
~TestException()
{
std::cerr<<this<<" - inside destructor"<<std::endl;
}
};
int main()
{
try
{
ThrowIt();
}
catch(TestException & ex)
{
std::cout<<"Caught exception ("<<&ex<<")"<<std::endl;
}
return 0;
}
void ThrowIt()
{
TestException ex;
throw ex;
}
Run Code Online (Sandbox Code Playgroud)
样本输出:
matteo@teolapubuntu:~/cpp/test$ g++ -O3 -Wall -Wextra -ansi -pedantic ExceptionStack.cpp -o ExceptionStack.x
matteo@teolapubuntu:~/cpp/test$ ./ExceptionStack.x
0xbf8e202f - inside default constructor
0x9ec0068 - inside copy constructor
0xbf8e202f - inside destructor
Caught exception (0x9ec0068)
0x9ec0068 - inside destructor
Run Code Online (Sandbox Code Playgroud)
顺便说一句,你可以在这里看到用于抛出对象的内存位置(0x09ec0068)肯定远离原始对象(0xbf8e202f):堆栈像往常一样具有高地址,而内存用于抛出的对象在虚拟地址空间中完全失效.尽管如此,这是一个实现细节,因为正如其他答案所指出的那样,该标准没有说明抛出对象的内存应该在何处以及应该如何分配.
归档时间: |
|
查看次数: |
2431 次 |
最近记录: |