如果 c 代码"through"抛出异常会发生什么?

What happens if exception gets thrown "through" c code?

本文关键字:什么 抛出异常 代码 through 如果      更新时间:2023-10-16

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

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

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

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

当然,一种可能性是将C代码编译为C++,同时检查它是否与异常无关。

问题的答案是定义实现。

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

然而,C代码本身可能不会出现异常

acquire a resource
do some stuff
release resource

这里的"获取资源"可以是指mallocpthread_mutex_lockfopen。如果您的C++代码是"做一些事情"的一部分,并且它抛出了一个异常,那么。。。哇。

资源泄漏并不是唯一的问题;正确性也是普遍的。想象一下:

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

现在想象一个异常在第一步完成之后,但在第二步完成之前抛出。

简言之,尽管您的实现可能提供了一种让您通过C代码抛出异常的方法,但这是一个坏主意,除非您也编写了知道异常可能抛出的确切位置的C代码。

  1. 编译时启用了异常
  2. 异常安全

对于您的C或C++代码来说,如果:

  1. 在抛出异常和捕获异常之间不需要明确地收集资源

使用C++异常支持编译的代码添加了特殊的钩子,以便在抛出异常且未在该范围内捕获异常时进行清理。在堆栈上分配的C++对象将调用它们的析构函数。

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

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

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

异常通常不会真正抛出"through"代码;正如操作所暗示的那样,它们被抛出"over"代码。

例如;至少老派的Objective-C异常通常使用setjmp和longjmp来实现;本质上存储代码的地址以供以后使用。

用类似的机制实现C++异常是有意义的;因此;异常被抛出的代码类型是"through",或者更准确地说是"over",这无关紧要。甚至可以想象这样一种设置,其中Objective-C异常被抛出到C++捕获上,反之亦然。

编辑:作为Bo Persson mentiones;这并不是说C++异常中断C代码不会造成严重破坏和泄漏;但是抛出异常通常是件坏事™全面;所以这不太重要。

PS:真的问了一个问题,同时使用C和C++标记在哪里是相关的,值得称赞。)

C对异常一无所知,因此无法说明会发生什么。

要编写一致的代码,您需要在返回到C库之前捕获异常,转换为错误代码,然后将C库错误转换回另一端的异常。