无法捕捉异常!

问题描述:

我正在使用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()方法。

有什么想法?

+1

确定您的连接方法是否已输入?您可以调试您的代码并在调试器中单步执行它。这应该告诉你问题在哪里。 – lothar 2009-05-27 01:08:06

+0

是的,connect方法是绝对进入的,我在上面的代码中省略了它们,但是在分配给_monitor之前和之后,在try块中有printf和fflush(stdout)。之前打印的是一个,但Monitor的构造函数抛出异常,第二个没有输出。 关于调试,你有什么指针?由于它实际上是调用这些方法的python代码,所以在这种情况下,我对调试知之甚少。基本的gdb技巧会起作用吗? – chase 2009-05-27 20:07:33

+0

也许Monitor构造函数捕获异常并在内部终止运行时...? – harto 2009-05-28 03:25:26

我不熟悉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"); 
} 
}