我们有一个第三方库,编写时没有考虑多线程或异常处理。我们的主要可执行文件是多线程的并使用异常。
第三方库使用exit()
中止程序以解决严重问题(例如"驱动程序未初始化"或"文件未找到")。不允许在多线程应用程序中调用exit()
,因为它不能正确关闭线程。另外,我真的不想退出主应用程序,因为它是一个服务器应用程序,并且在许多情况下,主程序可以采取主动的措施来从错误中恢复。
我想基本上用我自己的函数替换系统提供的exit(int status)
函数,即
class exit_exception : public runtime_error
{
public: exit_exception(int status)
: runtime_error("exit called with status " + to_string(status)) {}
};
extern "C" void exit(int status) {
throw exit_exception(status);
}
并在我的代码中捕获异常。它似乎有效,但这显然是一种黑客攻击,而不是自然意图exit()
使用的方式。在不知情的情况下我做错了什么?
许多人建议我把它放在一个单独的过程中,但这会打败很多东西。第三方库执行非常高速的数据传输,需要在主应用程序进程中,因为它位于相同的虚拟内存空间中,并且不使用malloc
从作为控制器的FPGA协处理器分配内存。这段代码接近" iron"并且正在从存储器和PCIe总线中挤出每一点带宽。
我的程序仍然可以使用int main()
的返回值将状态代码返回给操作系统,而不最终会调用exit()
。否则我会遇到麻烦。
答案 0 :(得分:1)
这只是一个想法,但你可以使用类似的方法,就像我需要将memcpy
包装成使用某个不同的版本时一样,看一下我的回答here。
因此,您可以构建一个不执行任何操作的exit()
函数的替换,或者进行一些清理。这只是一个想法,我没有尝试过,但它可以帮助您解决问题。
答案 1 :(得分:1)
最大和最明显的风险是资源泄漏。 如果库认为其错误处理策略是从最近的窗口中跳出,则总是存在抛出该异常不会导致组织良好的内存和系统资源释放的风险。
但是我注意到你提到它没有用malloc()
分配内存,如果这意味着你必须提供它作为缓冲区之类的所有资源,那么可能是因为一些神奇的意外它可以安全地解开!
如果失败了我可以建议联系供应商并说服他们应该加入我们其他人的第21个编程范例。
PS:从atexit()
处理程序中抛出异常会导致C ++程序终止。因此添加投掷处理程序不是一种选择。
如果其他库在您之后插入'atexit()'处理程序,它也不是一个选项。
答案 2 :(得分:0)
您可以尝试将atexit()
处理程序与longjmp
一起使用。虽然行为未定义:)
另一种方法是在一个单独的进程中运行lib,与任何IPC桥接。更难,更乏味,但更安全。
或者,您可以尝试扫描二进制图像并挂钩任何exit()
调用。我知道MS绕道而且在窗户上徘徊。不幸的是,虽然我在linux上都不知道。