尝试/赶上,以避免.stackdump

问题描述:

在下面的代码中,我在python模块代码中使用try/catch。在try块中,我有一个简单的错误(内存访问冲突),并试图捕获相应的异常并安静地终止程序,而不生成.stackdump文件。然而,后者仍然生成暗示try/catch构造不能完成它的工作。我怎样才能避免生成.stackdump文件并在不正确的操作(如代码中的一个)得到满足时退出程序? P.S.我正在编制在Cygwin中的代码用gcc和Boost.Python的尝试/赶上,以避免.stackdump

有趣的是,它没有的情况下,仅x[3]=2工作,而是适用于所有其他情况:例如x[4]=2x[20]=2,或者显然,x[2]=2

#include <boost/python.hpp> 
#include <iostream> 
#include <iomanip> 
using namespace std; 
using namespace boost::python; 


class Hello 
{ 
    std::string _msg; 

public: 

    Hello(std::string msg){_msg = msg;} 

    void run(){ 
     try{ 

     double* x; 
     x = new double[3]; 
     x[3] = 2.0; 
     delete [] x; 


     }catch(...){ exit(0); } 

    } 

}; 


BOOST_PYTHON_MODULE(xyz) 
{ 
    class_<Hello>("Hello", init<std::string>()) 
     .def("run",&Hello::run) 
    ; 

} 

编辑:

根据什么Maciek曾建议我尝试以下窍门:

进行信号处理函数抛出一个异常,但不退出

void sig_action(int signo) { 
    std::cout << "SIGNAL " << signo << std::endl; 
    throw 1; 
// exit(0); 
} 

现在尝试在try/catch块中放置一个可能有问题的函数(信号函数放在类构造函数中):

class Hello 
{ 
    std::string _msg; 

public: 

    Hello(std::string msg){ 
    _msg = msg; 
     signal(SIGABRT, sig_action); 
     signal(SIGSEGV, sig_action); 

    } 
    void set(std::string msg) { this->_msg = msg; } 
    std::string greet() { return _msg; } 

    void run(){ 

     try{ 
     double* x; 
     x = new double[3]; 
     x[3] = 2.0; 
     delete [] x; 

     }catch(...){ cout<<"error in function run()\n"; exit(0); } 

    } 

}; 

但是这样一招行不通,因为我希望它产生以下输出:

SIGNAL 6 
terminate called after throwing an instance of 'int' 
SIGNAL 6 
terminate called recursively 
SIGNAL 6 
terminate called recursively 
.... 
(and many more times the same) 

所以抛出异常,但它已被抓之前一切结束。有什么办法让它在终止这个过程之前被抓到?

您只能捕获抛出的异常。无效的指针访问不会引发异常,它只会导致未定义的行为,并且在您的特定情况下会导致堆栈转储。

如果您想要了解这种情况,请使用std::vectorat function访问项目。当与无效索引一起使用时,这将抛出std::out_of_range。但是,通常最好先避免这种访问的可能性,因为它们通常指示程序中的错误,并且错误不应该通过例外来处理,它们应该从代码中移除。

+0

谢谢。事实上,这就是我如何找到一个错误 - 通过找到引发异常的代码(很可能是内存访问的一些问题)的一部分。我知道这不是应该如何找到一个错误,但它是我目前唯一的方式 - 它的一个长长的故事。我还添加了一些更正 - 似乎仍然抛出异常,但不是所有情况下;但在其中大部分。 – user938720 2013-03-24 21:07:35

在Linux上,核心转储由信号处理程序生成,默认操作设置为coreSIGABRTSIGSEGV,...)。如果你想避免核心转储,你总是可以捕获/忽略这些信号。它也应该在Cygwin stackdumps上工作。但是你仍然可能会得到一些令人讨厌的消息作为输出。

编辑:

#include <signal.h> 

// [...] 

void sig_action(int signo) { 
    std::cout << "SIGNAL " << signo << std::endl; 
    exit(0); 
} 

int main(int argc, char* argv[]) { 
    signal(SIGABRT, sig_action); 
    signal(SIGSEGV, sig_action); 

    Hello h("msg"); 
    h.run(); 
} 
+0

不知道如何使用它。你能否提供一些细节如何在代码中包含这些内容(例如,例子中的那个)? – user938720 2013-03-24 22:45:14

+0

我已经添加了一个示例代码。如果您只是想忽略该信号,请使用'SIG_IGL'作为动作功能 – 2013-03-24 22:56:42

+0

谢谢Maciek。这是一般工作,但它是否有可能检查代码的哪一部分出现问题?例如,让我们说我们有另一个没有错误的函数run1(比如在原始运行中)并调用这两个函数。在信号使用的基础上,我怎么知道哪一个会导致这个问题呢?使用try/catch构造,可以将每个函数括起来并区分哪一个包含错误。是否有可能做这样的信号功能? – user938720 2013-03-24 23:12:08