c++保护对公共函数的访问

c++ Protect access to public functions

本文关键字:函数 访问 保护 c++      更新时间:2023-10-16

我有一个engine.dll模块,它实现了几个处理功能,我创建了一个PublicInterface.h,定义了外部访问的函数,

namespace PublicInterface {
  void do_a();
  void do_b();
}

我想保证对PublicInterface中函数的每个调用都受到try-catch块的保护。换句话说,我希望engine.dll能够处理它抛出的所有异常。实现这一点的最佳方式是什么?

我想创建一个附加功能

void protectedRun(std::function<void()> f) {
try {
    f();
}
catch (...) {
    _handle();
}

但是,我如何强制PublicInterface.h中的所有函数都将从protectedRun()调用呢?

或者有更好的方法来实现这一点吗?

解决方案取决于您想要实现的目标:

如果您希望用户处理代码中所有可能的异常,那么没有直接的方法可以强制他们使用protectedRun调用函数。C++没有Java的检查异常。

如果您想确保代码中没有异常传播到调用方的代码,例如,您可以添加一个处理所有异常的新公共接口,并(可选)将当前公共接口设为私有接口。

简而言之,要么用户可以访问代码中的异常(可能不处理它们),要么他不会(也没有任何处理它们的选项)。

实现如下:

using exceptionHandler = void(*)(std::exception& e);
void defaultHandler(std::exception& e) { throw e; }
namespace PublicInterface {
  void do_a(exceptionHandler eh = &defaultHandler);
  void do_b(exceptionHandler eh = &defaultHandler);
}

在函数内部,不要直接抛出,而是将异常传递给(*eh)()

唯一真正的方法是不要将抛出异常的函数放入公共接口。相反,将protectedRun()函数放在公共接口中,让它调用抛出函数,捕获这些异常,并(最重要的)纠正导致抛出异常的问题。

然而,从根本上讲,函数抛出异常并试图强制执行捕获异常的方式,这表明您的库存在严重的设计缺陷。

异常的全部意义在于报告错误条件的机制,该错误条件(a)在检测到条件的情况下无法纠正,(b)在发生任何其他情况(程序终止除外)之前必须纠正条件。

试图规定调用方必须立即捕获异常并更正原因是毫无意义的。如果调用程序无法更正原因,但无论如何都被迫捕获,那么唯一可用的选项就是重新引发异常。除了捕获和重新抛出的额外运行时开销外,这与调用方根本不捕获异常具有相同的效果(堆栈展开)。

您需要做的是仔细考虑库中的函数抛出异常是否合适。因为捕获异常不是库函数调用方的责任。库函数有责任以对调用者有意义的方式抛出异常。

还有一个基本问题是,根据您的工具链(用于构建DLL的编译器、链接器等与用于构建调用程序的编译器、连接器等)和环境(主机系统等)的不同,异常可能无论如何都不会完全跨越DLL边界。