如果exception被“通过”c代码抛出会发生什么?

可能重复:
C ++exception会通过C代码安全传播吗?

如果您有c代码,例如png lib,您自己的io处理程序是用c ++编写的,并且由于某些io错误而引发exception。 让它通过c代码并在c代码之外捕获它是否可以? 我知道必须注意内存泄漏,但通常所有结构都要预先分配。

完全取决于编译器是否可行。 没有一种语言标准可以明显地说出其他语言应该做什么。

在最好的情况下,exception将传递C代码并返回到下一个C ++级别,同时可能泄漏任何动态分配的C结构。 在不太好的情况下,它会崩溃和燃烧!

一种可能性当然是将C代码编译为C ++,同时还检查它是exception中性的。

你的C ++代码是可以的,如果它是:

  1. 编译时启用了例外。
  2. 例外安全。

如果符合以下条件,您的C或C ++代码就可以了:

  1. 在抛出exception和被捕获之间不需要显式收集资源。

使用C ++exception支持编译的代码添加了特殊的挂钩,以便在抛出exception时清除并且不会在该范围中捕获。 在堆栈上分配的C ++对象将调用其析构函数。

抛出exception时在C(或C ++中无exception支持)中回收的唯一资源是在每个堆栈帧中分配的空间。

GCC手册的这一部分非常有用:

  -fexceptions
           启用exception处理。 生成所需的额外代码
           传播例外。 对于某些目标,这意味着GCC会
           生成所有函数的帧展开信息,可以
           尽管它没有影响,但会产生大量的数据大小开销
           执行。 如果您未指定此选项,GCC将启用它
           默认情况下,通常需要exception的C ++等语言
           处理,并禁用C语言,通常不正常
           需要它。 但是,您可能需要在启用此选项时
           编译需要与exception正确互操作的C代码
           用C ++编写的处理程序。 您可能还希望禁用此选项
           如果您正在编译不使用exception的旧C ++程序
           处理。 

您的问题的答案是实现定义。

对于GCC,正如@Kerrek所说,使用-fexceptions编译C代码将确保在通过C代码抛出exception时运行时保持一致。 (请注意,现代exception机制不仅仅通过setjmp / longjmp实现;它们实际上是逐帧展开堆栈,以便正确处理析构函数和try / catch块。)

但是,C代码本身可能不会期望通过它抛出exception。 很多C代码都是这样编写的:

 acquire a resource do some stuff release resource 

这里“获取资源”可能意味着malloc ,或pthread_mutex_lock ,或fopen 。 如果你的C ++代码是“做一些东西”的一部分,它会抛出exception,那么……哎呀。

资源泄漏不是唯一的问题; 所以正确性是一般的。 想像:

 subtract $100 from savings account add $100 to checking account 

现在假设在第一步完成后但在第二步完成之前抛出exception。

简而言之,虽然您的实现可能提供了一种让您通过C代码抛出exception的方法,但这是一个坏主意,除非您还编写了C代码,知道可能引发exception的确切位置。

通常不会通过代码抛出exception; 正如动作所暗示的那样,它们被抛到了“代码”之上。

作为一个例子; 至少老派的Objective-Cexception通常用setjmp和longjmp实现; 本质上存储代码的地址供以后使用。

使用类似的机制实现C ++exception是有意义的; 就这样; “通过”抛出exception的代码类型,或者更确切地说,“过度”抛出的代码类型很少,如果有的话。 人们甚至可以想象一个设置,其中一个Objective-Cexception被抛出C ++ catch,反之亦然。

编辑:正如博佩森提到的那样; 这并不是说中断C代码的C ++exception不会造成破坏和泄漏; 但抛出的exception通常都是Bad Thing™; 所以它不太重要。

PS: Kudos实际上在问一个问题,其中使用C和C ++标签是相关的。 ;)

C对exception一无所知,所以不可能说出会发生什么。

要编写符合规范的代码,您需要在返回C库之前捕获exception,转换为错误代码,然后将C库错误转换回另一端的exception。