跨DLL边界抛出C++异常

Pau*_*cas 28 c++ dll exception-handling

我已经阅读了有关如何不在一个DLL中分配堆内存并从该DLL外部解除分配的各种事项.但是抛出一个只是临时的异常对象(如大多数异常对象)呢?例如:

throw my_exception( args ); // temporary: no heap allocation
Run Code Online (Sandbox Code Playgroud)

当异常对象被捕获到DLL外部时,最终将执行该对象的析构函数,并将回收该对象的非堆内存.这样可以,因为它不是堆内存吗?

Ben*_*igt 25

只有当所有模块使用相同的C++运行时时,才能跨DLL边界抛出C++异常,在这种情况下,它们也共享一个堆.但这可能是一种维护负担,尤其是涉及多个供应商的库时,因此不鼓励这样做.

如果您想要在多个编译器/编译器版本/编译器设置中可移植的错误处理,请使用返回代码或OS提供的异常(例如Windows上的SEH)/

  • @Paul:这不是异常结构的问题,它是编译器的内部数据,用于查找匹配的catch块并执行堆栈展开,所有这些都是高度特定于编译器的,并且可能使用全局变量,甚至可能使用堆.如果所有模块都没有共享运行时,则会遇到问题. (11认同)

0xC*_*22L 1

这取决于内存的分配方式以及分配机制(“运行时”或“内存管理器”)是否在特定 DLL 和应用程序的其他部分之间共享。throw new my_exception( args );例如,根据细节,a也可能是有序的。

您可以对异常进行引用计数,以便它具有如何销毁其自己的实例(和拥有的内存)的内在知识。

使用IMalloc(参见 MSDN)作为实例分配和放置new将是另一种方式(OleInitialize之前调用)...

事实上,内存分配是一个问题,具体取决于所使用的内容。例如,在应用程序的不同部分混合静态链接的 CRT 和动态链接的 CRT 会导致问题,就像混合调试和发布代码一样。这里的问题是,应该释放内存的代码使用了不同的“内存管理器”。但是,如果抛出的对象知道它自己的销毁,那么应该没问题,因为 dtor 代码将驻留在与分配它的编译单元相同的编译单元中。