【发布时间】:2011-12-08 13:00:52
【问题描述】:
我不是在问 C++ 异常通过 C 代码传播是否安全,也不是在这种情况发生时会发生什么。我在 SO(1, 2, 3) 和 this FAQ 中阅读了以下问题。我在问如何继续:
- 避免将任何 C++ 异常泄露给 C 代码(这意味着在调用 C 代码之前捕获 C++ 领域中的所有异常)
- 还能够捕获 C 代码之外的异常(在更高的 C++ 代码中)。
让我说明一下我的想法:
假设libfoo 是一个C 库,我想在我的bar C++ 程序中使用它。 libfoo 需要我必须提供的回调函数 foo_callback。我的回调中使用的函数和方法可能会抛出异常,所以我写了:
void my_callback(void)
{
try
{
// Do processing here.
}
catch(...)
{
// Catch anything to prevent an exception reaching C code.
// Fortunately, libfoo provides a foo_error function to
// signal errors and stop processing.
foo_error() ;
}
}
然后我使用如下所示的回调:
// The bar program.
int main()
{
// Use libfoo function to set the desired callback
foo_set_callback(&my_callback) ;
// Start processing. This libfoo function uses internally my_callback.
foo_process() ;
// Check for errors
if( foo_ok() )
{
// Hurray !
}
else
{
// Something gone wrong.
// Unfortunately, we lost the exception that caused the error :(
}
}
我想要的是能够在main 函数中捕获从my_callback 抛出的异常,而不会通过libfoo 传播异常(是的,这是一种通过C 进行quantum tunnelling 实验的量子异常代码)。
所以我想使用的代码:
void my_callback(void)
{
try
{
// Do processing here.
}
catch(...)
{
// Catch anything to prevent an exception reaching C code.
// We save the exception using (the magic) ExceptionHolder.
ExceptionHolder::Hold() ;
// Call foo_error function to signal errors and stop processing.
foo_error() ;
}
}
// The bar program.
int main()
{
// Use libfoo function to set the desired callback
foo_set_callback(&my_callback) ;
try
{
// Start processing. This libfoo function uses internally my_callback.
foo_process() ;
// Once gone out of the C land, release any hold exception.
ExceptionHolder::Release() ;
}
catch(exception & e)
{
// Something gone wrong.
// Fortunately, we can handle it in some manner.
}
catch( /*something else */ )
{
}
// ...
}
鉴于以下限制:
-
libfoo是源代码封闭的,用 C 语言编写,并以供应商的编译格式提供。在库上进行的测试表明异常不能通过它传播。我无法访问源文件,也无法获得支持异常的编译版本。 - 回调函数广泛使用了使用异常的 C++ 代码。所有的错误处理都是围绕异常机制构建的。我绝对不能简单地使用吞下所有异常的代码。
- 不涉及多线程。
- 不支持 c++0x。
我的问题:
- 它是否已经被某些库或某些 C++ 魔法(如
boost)甚至 c++0x 解决了? - 如果不是,我如何编写一个适用于任何异常类型的 ExceptionHolder ?我对 C++ 很满意,但我还没有找到一种方法来编写一个可靠且易于使用的 ExceptionHolder,它适用于任何异常类型。
非常感谢您的建议!
编辑:我添加了一个响应,其中包含一些异常保持/释放机制的实现。欢迎所有批评或建议。
【问题讨论】: