c++ - 混合 C 和 C++ 代码时确保异常传播的机制

标签 c++ c exception

我不是在问 C++ 异常通过 C 代码传播是否安全,也不是在问发生这种情况时会发生什么。我在 SO( 123 )和 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。

非常感谢任何建议!


编辑:我添加了一个带有一些异常保持/释放机制实现的响应。欢迎所有批评或建议。

最佳答案

我相信 boost.exception 有一种机制可以适应您的目的。请参阅此处获取灵感:

http://www.boost.org/doc/libs/1_47_0/libs/exception/doc/tutorial_exception_ptr.html

它似乎是为了在线程之间传递它们的特殊异常类型,但我认为这几乎是一回事——阻止异常传播到线程边界或 C 代码边界,将它的拷贝隐藏在指针,然后通过边界另一侧的指针检索它,并可选择重新抛出它。

我不确定让您自己的异常派生自 boost 的神奇异常类型是否可行,但如果我没记错的话,大约一年前使用它时,它是相当合理的。

关于c++ - 混合 C 和 C++ 代码时确保异常传播的机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7781342/

相关文章:

c# - Parallel.ForEach 中的异常堆栈跟踪和聚合

c++ - 添加空间隔 Widget 导致 Qt 中的内存泄漏?

c++ - 如何为字符数组制作模板函数特化?

c++ - 如何创建文件路径可以像磁盘一样访问的虚拟文件系统

c - 在循环中使用 If 语句时出现段错误

c - 在 Raspberry PI 3 上的 C++ 中达到超时后如何清除 select() 状态

c - c中的链表子串

c++ - 在 Windows 应用商店应用程序中启用抗锯齿

python - 在 Django 模板中捕获异常

visual-studio - 在 VS2012 中切换 'break on all exceptions' 的快速方法?