库中的exit()是否可以替换为引发异常? 我用C++的C/FORTRAN库工作,库调用Ext()。我希望它抛出一个异常,以便调用C++程序中的析构函数。我已经能够创建一个抛出异常的exit定义,但是仍然调用terminate。是否存在防止调用terminate并允许正常异常处理发生的方法

库中的exit()是否可以替换为引发异常? 我用C++的C/FORTRAN库工作,库调用Ext()。我希望它抛出一个异常,以便调用C++程序中的析构函数。我已经能够创建一个抛出异常的exit定义,但是仍然调用terminate。是否存在防止调用terminate并允许正常异常处理发生的方法,c++,c,exception,C++,C,Exception,更新:在评论中指出,这在x64上有效,但在x86上失败,所以主要问题是“有没有办法让x86像x64一样工作?” 更新2:查看我的回复,了解为什么x86上无法使用此功能以及如何修复它 以下是我的测试代码: test_exception.c #include <stdlib.h> void call_c() { exit(1); } 我知道您可能不想读这篇文章,但在程序的任何部分尝试调用exit()或类似命令后继续执行程序很可能是错误的 如果程序的一部分名为exit(),则无法保证程

更新:在评论中指出,这在x64上有效,但在x86上失败,所以主要问题是“有没有办法让x86像x64一样工作?”

更新2:查看我的回复,了解为什么x86上无法使用此功能以及如何修复它

以下是我的测试代码:

test_exception.c

#include <stdlib.h>

void call_c() { exit(1); }

我知道您可能不想读这篇文章,但在程序的任何部分尝试调用
exit()
或类似命令后继续执行程序很可能是错误的

如果程序的一部分名为
exit()
,则无法保证程序在该点的状态。您不知道堆是否处于一致状态。你不知道这堆东西是否好。如果将
exit()
转换为
throw
,则每次发生这种情况时,最不可能遇到内存泄漏。您不知道是否可以安全地再次调用导致此错误的库

如果您已经检查了库的源代码,并且确定不会导致任何损坏,那么最干净的解决方案是修改库本身,以便它抛出而不是退出


如果不允许更改库,另一个干净且正确的解决方案是将库的所有使用放在一个单独的进程中,您可以监视并重新启动该进程。

上述代码可以工作,但在gcc 4.6之前的x86上,在构建C代码时需要添加,-feexceptions或-funwind表,以便可以展开堆栈。您可以看到.< /p>< p>除非您的C++实现被破坏,否则当调用“代码>退出<代码>时,它将调用全局变量的析构函数(GCC未被破坏,至少我尝试过的所有版本)。所以你只需要清理那些不会被全局变量的析构函数清理的东西

对于堆上的全局内容,可以使用
atexit
注册一个清理函数,该函数将在调用
exit
时调用——此清理函数可以
删除需要清理的任何堆对象


堆栈上内容的析构函数要复杂得多。最好的解决办法可能是确保这样的析构函数不需要调用——在退出之前必须清除的任何东西都应该被全局(可能使用静态成员类)引用,这在析构函数中进行清理。< /p> @ IHAROB:但是问题是C和C++之间的交互作用。(具体来说,在C调用的函数中抛出一个异常)@ iHAROB:这是一个C++程序,它的功能是用C编写的,而不是C程序。至于它看起来是什么样的:它看起来就像问题中的代码。也许你应该在进一步评论之前读这个问题。库调用“代码> Ext()有两个原因)
。第一种情况是程序员认为这是处理错误的有效方法,他们完全不懂。我更喜欢与这些库保持距离。另一种情况是正常错误处理无法修复的致命情况,例如,重要插件目录不存在或检测到一些编程错误。即使在那里,u使用
abort()
触发调试器将是首选。考虑到这一点,我同意David的问题,为什么库调用
exit()
。如果所有其他操作都失败,您可以通过
fork
调用来运行库。@πάνταῥεῖ:
at\u exit()
在这里没有真正的帮助。调用任何已注册函数后,程序仍然会终止。您可以在
at\u exit()
-已注册函数调用继续执行程序工作的内容,但之后再次调用
exit()
时(包括正常终止
main()
),行为未定义。我完全同意建议。抱歉,我在原始帖子中没有说得更清楚。我的意图不是“召回库”或“阻止程序退出”,但只是让所有的析构函数都被调用,以便能够正确地释放资源等等。程序应该尽可能地使用资源,使操作系统在程序退出时能够释放资源。在某些情况下,例如系统关闭,操作系统会在没有进一步通知的情况下杀死您的程序e、 该程序也可能被用户终止。它可能在SSH会话结束时被SSH服务器终止-这反过来可能是由于网络断开等简单且不可控的原因造成的。如果需要日志记录、信号或其他输出来指示退出的原因,我会从退出时执行的函数中触发。然后,出口
#include <iostream>
#include <stdexcept>

extern "C" void call_c();

extern "C" void exit(int value)
{
  throw std::runtime_error(std::string("Throwing an exception: ") + char('0' + value));
}

int main()
{
  try {
    call_c();
  } catch (const std::exception &e) {
    std::cerr << e.what() << std::endl;
    return 1;
  }

  return 0;
}
gcc -c test_exception.c -o test_exception_c.o
g++ -c test_exception.cpp -o test_exception_cpp.o
g++ test_exception_c.o test_exception_cpp.o -o test_exception