C++;是否实现了异常处理运行时? 我很好奇C++异常处理机制是如何工作的。具体来说,异常对象存储在哪里?它如何在多个作用域中传播,直到被捕获?它是否存储在某个全球区域

C++;是否实现了异常处理运行时? 我很好奇C++异常处理机制是如何工作的。具体来说,异常对象存储在哪里?它如何在多个作用域中传播,直到被捕获?它是否存储在某个全球区域,c++,exception,error-handling,language-implementation,C++,Exception,Error Handling,Language Implementation,由于这可能是特定于编译器的,有人能在g++编译器套件的上下文中解释一下吗?您可以查看详细的解释 了解一下在普通C中用于实现某种基本类型的异常处理的技巧也会有所帮助。这需要以以下方式使用setjmp()和longjmp():前者保存堆栈以标记异常处理程序(如“catch”),而后者用于“抛出”值。“抛出”值被视为是从被调用函数返回的。“try块”在再次调用setjmp()或函数返回时结束。这是在15.1中定义的,引发了标准的异常 抛出将创建一个临时对象。 未指定如何分配此临时对象的内存 创建临时对

由于这可能是特定于编译器的,有人能在g++编译器套件的上下文中解释一下吗?

您可以查看详细的解释


了解一下在普通C中用于实现某种基本类型的异常处理的技巧也会有所帮助。这需要以以下方式使用setjmp()和longjmp():前者保存堆栈以标记异常处理程序(如“catch”),而后者用于“抛出”值。“抛出”值被视为是从被调用函数返回的。“try块”在再次调用setjmp()或函数返回时结束。

这是在15.1中定义的,引发了标准的异常

抛出将创建一个临时对象。
未指定如何分配此临时对象的内存

创建临时对象后,控件将传递给调用堆栈中最近的处理程序。在投掷点和接球点之间展开堆叠。当堆栈展开时,所有堆栈变量都将按与创建相反的顺序销毁

除非重新抛出异常,否则将在捕获该异常的处理程序末尾销毁该临时异常

注意:如果按引用捕获,则引用将引用临时对象;如果按值捕获,则临时对象将复制到值中(因此需要复制构造函数)

S.Meyers的建议(按常量参考捕获)


实现可能会有所不同,但有一些基本的想法遵循需求

异常对象本身是在一个函数中创建的对象,在其调用者中销毁。因此,在堆栈上创建对象通常是不可行的。另一方面,许多异常对象不是很大。因此,如果实际需要更大的异常对象,可以创建一个32字节的缓冲区和溢出到堆中

至于控制权的实际转移,存在两种策略。一种是在堆栈本身中记录足够的信息,以便展开堆栈。这基本上是要运行的析构函数和可能捕获异常的异常处理程序的列表。当发生异常时,运行执行这些析构函数的堆栈,直到找到匹配的捕获


第二种策略将这些信息移动到堆栈外的表中。现在,当发生异常时,调用堆栈用于确定哪些作用域已输入但未退出。然后在静态表中查找这些异常,以确定将在何处处理抛出的异常,以及其间运行哪些析构函数。这意味着堆栈上的异常开销更少;无论如何都需要返回地址。表是额外的数据,但编译器可以将它们放在程序的按需加载段中。

我知道这是一个老问题,但这里有一个非常好的解释,解释了gcc和VC中使用的两种方法:

其他未指定的是程序如何展开堆栈以及程序如何知道堆栈的位置“最近的处理程序”是。我很确定Borland拥有一项实现该方法的专利。只要对象按创建的相反顺序销毁,除非你是一名编译工程师,否则实现细节并不重要。投票否决:a)“Scott Meyers”,而不是“S.Myers”;b)不真实的引用:“有效的C++”:第13项:通过引用捕获异常。“。这将允许对异常对象进行调整/附加信息。@phresnel:不要忘记第21项:“尽可能使用常量”。调整异常没有好的理由。你应该是a)“修复并丢弃”,b)重新抛出或c)生成新异常。@phresnel:是的,你有你的理由(不同意你的逻辑),我有我的,虽然我不会声称与他们谈论过这个特定的主题,也不会真正了解他们的想法(梅耶斯、亚历山德雷斯库和萨特),但我相信我的解释是正确的。但如果你在西雅图地区,那么你可以与他们三人交谈,因为他们是会议的常客AfAIR G++使用第二个地址表方法,大概是出于与微软兼容的原因。微软C++编译器使用组合方法,因为它的C++异常是建立在SEH(结构化异常处理)之上的。在每个C++函数中,MSC++将创建和注册一个SEH异常处理记录,指向一个表,该表中包含用于该特定函数中的TestCcatch块和析构函数的地址范围。然后,SEH将控制返回给C++特定的处理程序。@安顿:是的,它使用地址表方法。请参阅我的另一个问题的答案。详细的答案。谢谢你的答案。你可以看到C纯化论者如何害怕C++及其异常。嵌入式系统之所以经常避免使用额外的表,是因为您的程序花费了大量的时间或时间。@speedplane:不,这更多是因为缺乏理解。错误处理从来都不是免费的。C只是强迫您自己编写。我们都知道有多少C程序缺少
free()
fclose()
在一些很少使用的代码路径中。@MSalters我并不反对,这几乎完全是因为缺乏理解。工程师通常不了解异常是如何工作的,以及异常如何影响他们的代码,这就有理由导致在使用异常时犹豫不决。如果异常处理实现的沟通更加清晰(看起来并不像魔术),许多人会不太犹豫地使用它们。阅读这篇文章会帮助你我不知道-但是我猜C++规范有C。
try
{
    // do stuff
}
catch(MyException const& x)
{
}
catch(std::exception const& x)
{
}