LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 208|回复: 0

从非异常代码调用异常代码

[复制链接]
发表于 2024-2-6 22:37:48 | 显示全部楼层 |阅读模式
声明为 extern "C" 的 C++ 函数可由 C 程序调用。 C++ COM 服务器可由采用任意数量的不同语言编写的代码使用。 在使用 C++ 实现将由非异常代码调用的可识别异常的公共函数时,C++ 函数不得允许将任何异常传播回调用方。 此类调用方无法捕获或处理 C++ 异常。 程序可能会终止、泄露资源或导致未定义的行为。

我们建议让 extern "C" C++ 函数专门捕获它知道如何处理的所有异常,并根据需要将异常转换为调用方能理解的错误代码。 如果 C++函数并非了解所有可能的异常,它应将 catch(...) 块作为最后一个处理程序。 在这种情况下,最好向调用方报告错误,因为你的程序可能处于未知且无法恢复的状态。

以下示例演示了一个函数,该函数假定可能引发的任何异常是 Win32Exception 或者属于派生自 std::exception 的异常类型。 该函数将捕获这些类型的任何异常并将错误信息作为 Win32 错误代码传递给调用方。

BOOL DiffFiles2(const string& file1, const string& file2)
{
    try
    {
        File f1(file1);
        File f2(file2);
        if (IsTextFileDiff(f1, f2))
        {
            SetLastError(MY_APPLICATION_ERROR_FILE_MISMATCH);
            return FALSE;
        }
        return TRUE;
    }
    catch(Win32Exception& e)
    {
        SetLastError(e.GetErrorCode());
    }

    catch(std::exception& e)
    {
        SetLastError(MY_APPLICATION_GENERAL_ERROR);
    }
    return FALSE;
}
从异常转换为错误代码时,有一个潜在问题:错误代码包含的信息通常不及异常可存储的信息丰富。 要解决此问题,可为每个可能引发的具体异常类型提供一个 catch 块,并在异常转换为错误代码前执行日志记录以记录异常的详细信息。 如果多个函数都使用同一组 catch 块,此方法可能产生重复代码。 避免代码重复的一个好方法是,将这些块重构到一个实现 try 和 catch 块并接受 try 块中调用的函数对象的专用实用工具函数中。 在每个公用函数中,将代码传递到实用工具函数以作为 lambda 表达式。

template<typename Func>
bool Win32ExceptionBoundary(Func&& f)
{
    try
    {
        return f();
    }
    catch(Win32Exception& e)
    {
        SetLastError(e.GetErrorCode());
    }
    catch(const std::exception& e)
    {
        SetLastError(MY_APPLICATION_GENERAL_ERROR);
    }
    return false;
}
以下示例演示如何编写函数定义的 lambda 表达式。 lambda 表达式通常比调用命名函数对象的代码更容易内联读取。

bool DiffFiles3(const string& file1, const string& file2)
{
    return Win32ExceptionBoundary([&]() -> bool
    {
        File f1(file1);
        File f2(file2);
        if (IsTextFileDiff(f1, f2))
        {
            SetLastError(MY_APPLICATION_ERROR_FILE_MISMATCH);
            return false;
        }
        return true;
    });
}
若要详细了解 lambda 表达式,请参阅 lambda 表达式。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表