无法捕捉异常!
我正在使用swig从Python库中用Python包装类。它总体上工作,但有一个例外是从库内引发的,我似乎无法在swig界面中捕获它,所以它只是崩溃了python应用程序!无法捕捉异常!
PyMonitor.cc类描述了Swig接口到所需的类Monitor。 如果监视器的构造函数无法连接,则会引发异常。我想,以处理PyMonitor此异常,如:
PyMonitor.cc:
#include "Monitor.h"
// ...
bool PyMonitor::connect() {
try {
_monitor = new Monitor(_host, _calibration);
} catch (...) {
printf("oops!\n");
}
}
// ...
然而,connect()方法从来没有捕获该异常,我只是得到抛出后“终止调用。 ..“错误,程序中止。
我不太了解swig,但在我看来,这是一切正常的C++,异常应该在杀死程序之前传播到connect()方法。
有什么想法?
我不熟悉swig,或者一起使用C++和Python,但如果这是在最新版本的Microsoft Visual C++下,那么Monitor
类可能会抛出C结构化异常,而不是C++类型例外。 C结构化异常不会被C++异常处理程序捕获,即使是catch(...)
之一。
如果是这种情况,可以使用__try/__except
关键字(而不是try/catch
),或使用_set_se_translator
函数将C结构化异常转换为C++类型异常。
(老版本的MSVC++的处理Ç结构化异常和C++ int
类型和是用C++处理程序捕获,如果我没有记错。)
如果不是微软的Visual C下 ++,然后我不确定这是怎么发生的。
编辑:既然你说这不是MSVC,也许别的什么东西在你的代码获得它之前捕捉异常(并终止程序),或者你的catch块中有东西引发另一个异常?没有更多的细节可以处理,那些是我能想到会导致这些症状的唯一情况。
监视器constructor
直接或间接调用的函数可能违反了其异常规范,并且不允许抛出std::bad_exception
。如果你还没有取代标准函数来捕捉这个,那么它会解释你所看到的行为。
为了检验这一假设,你可以尝试定义自己的处理程序:“不好的事情发生”
void my_unexpected()
{
std::cerr << "Bad things have happened!\n";
std::terminate();
}
bool PyMonitor::connect() {
std::set_unexpected(my_unexpected);
try {
_monitor = new Monitor(_host, _calibration);
} catch (...) {
printf("oops!\n");
}
}
如果你拿到了错误消息,那么你已经确认这种情况,但不幸的是,你可以做的事情并不多。如果你'幸运',你可能会抛出一个异常,从my_unexpected
异常说明当前失败的函数允许,但在任何情况下,你的意外的处理程序不允许正常终止。它必须抛出或以其他方式终止。
为了解决这个问题,你真的需要进入被调用的代码并纠正它,以便不违反例外规范,既可以通过修改规范本身,也可以通过修复代码来避免抛出异常没有预料到。
另一种可能性是在抛出原始异常导致堆栈展开期间抛出异常。这也会导致过程终止。在这种情况下,尽管您可以替换标准终止函数,但您别无选择,只能放弃该程序。终止处理程序不允许抛出或返回,它必须终止程序。
如果你想解析它们,你必须将异常转发给Python。 查看SWIG Documentation。 为了转发异常,您只需在SWIG界面(.i)文件中添加一些代码即可。基本上,这可以在.i文件中的任何位置。
所有类型的异常应在此处指定,并痛饮仅捕捞上市的异常类型(在这种情况下的std :: runtime_error,性病:: invalid_argument,的std :: out_of_range),所有其他异常引起的未知异常(并因此被正确转发!)。
// Handle standard exceptions.
// NOTE: needs to be before the %import!
%include "exception.i"
%exception
{
try
{
$action
}
catch (const std::runtime_error& e) {
SWIG_exception(SWIG_RuntimeError, e.what());
}
catch (const std::invalid_argument& e) {
SWIG_exception(SWIG_ValueError, e.what());
}
catch (const std::out_of_range& e) {
SWIG_exception(SWIG_IndexError, e.what());
}
catch (...) {
SWIG_exception(SWIG_RuntimeError, "unknown exception");
}
}
确定您的连接方法是否已输入?您可以调试您的代码并在调试器中单步执行它。这应该告诉你问题在哪里。 – lothar 2009-05-27 01:08:06
是的,connect方法是绝对进入的,我在上面的代码中省略了它们,但是在分配给_monitor之前和之后,在try块中有printf和fflush(stdout)。之前打印的是一个,但Monitor的构造函数抛出异常,第二个没有输出。 关于调试,你有什么指针?由于它实际上是调用这些方法的python代码,所以在这种情况下,我对调试知之甚少。基本的gdb技巧会起作用吗? – chase 2009-05-27 20:07:33
也许Monitor构造函数捕获异常并在内部终止运行时...? – harto 2009-05-28 03:25:26