C++ 如何重写exit(),可能是通过引发异常

C++ 如何重写exit(),可能是通过引发异常,c++,c,C++,C,我们有一个第三方库,它是在没有考虑多线程或异常处理的情况下编写的。我们的主要可执行文件是多线程的,并且使用异常 第三方库使用exit()。不允许在多线程应用程序中调用exit(),因为它无法正确关闭线程。此外,我真的不想退出主应用程序,因为它是一个服务器应用程序,在许多情况下,主程序可以做一些主动的事情来从错误中恢复 我想基本上用我自己的函数替换系统提供的exit(int status)函数,即 class exit_exception : public runtime_error {

我们有一个第三方库,它是在没有考虑多线程或异常处理的情况下编写的。我们的主要可执行文件是多线程的,并且使用异常

第三方库使用
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协处理器分配内存。此代码接近“铁”,正在从内存和PCIe总线中挤出每一位带宽

编辑2
我的程序仍然可以使用
int main()
中的返回值将状态代码返回到操作系统,该返回值最终不会调用
exit()
。否则我会遇到真正的麻烦。

这只是一个想法,但你可以使用类似的方法,就像我需要包装
memcpy
时一样。要使用不同的版本,请查看我的答案


因此,您可以构建一个不执行任何操作的
exit()
函数的替换项,或者进行一些清理。这只是一个想法,我没有尝试过,但它可以帮助您解决问题。

您可以尝试将
atexit()
处理程序与
longjmp
一起离开。虽然行为未定义:) 另一种方法是在单独的进程中运行lib,并与任何IPC桥接。更难,乏味,但更安全。
或者,您可以尝试扫描二进制图像并钩住任何
exit()
调用。我知道微软的detours和windows上的mhook。不幸的是,虽然我对linux一无所知。

最大、最明显的风险是资源泄漏。 如果库认为它的错误处理策略是跳出最近的窗口,那么抛出该异常将不会导致内存和系统资源的有序释放

然而,我注意到您提到它不使用
malloc()
分配内存,如果这意味着您必须为它提供所有的资源作为缓冲区等等,那么可能由于某种奇迹般的意外,它是安全不可解的

如果失败了,我所能建议的就是联系供应商,说服他们加入我们的21世纪编程范例

<强> Ps:<强> >从<代码> ATEXIT()//Cux>处理程序中引发异常,导致C++程序的终止。因此,添加抛出处理程序不是一个选项。


如果其他库在您的处理程序之后插入“atexit()”处理程序,则也不能使用该选项

如果库是在没有考虑多线程的情况下编写的,那么重写
exit()
是否足以使其在多线程环境中表现良好似乎是值得怀疑的。通过使用
atexit()
,您可能会获得一些正在寻找的功能。我还没有充分利用这一点来知道你是否能够最终摆脱退出,但至少你可以监控有序关闭,甚至触发重新启动。这不是一个完美的解决方案,但可能有用。唯一好的解决方案是在自己的进程中隔离第三方库。@MarkLakata:共享内存应注意让硬件直接传输到主应用程序的内存空间,同时防止库损坏主应用程序中的任何其他内容。你认为一个单独的进程会破坏性能的假设导致了一个XY问题。@马克:特别是,我认为使用
clone(clone\u VM)
启动沙盒进程可能会有帮助。这看起来很有趣,我想尝试一下(但我不知道怎么做,所以这可能对将来的使用有用),但我现在所拥有的一切都很有效,看起来更干净。我更关心我的方法有什么不好的地方。这比我的异常方法好吗?我完全赞成把事情做得更好,但这听起来更老套、更危险。@MarkLakata:
longjmp
和抛出异常几乎是等价的。这个答案的优点是
atexit()
bit——您不必忙于动态修改代码,您可以通过让处理程序有条件地正常返回,返回到
exit
的原始行为。