在下面的代码中,我在python模块代码中使用try/catch
。在try
块中,我有一个简单的错误(内存访问冲突)并尝试捕获相应的异常并安静地终止程序而不生成.stackdump
文件。然而,后者仍然生成了暗示try/catch
构造不起作用的东西。如果满足不正确的操作(如代码中的操作),我怎么能避免生成.stackdump
文件并退出程序而不会出错?
附:我正在用gcc和boost.python
有趣的是,它仅在x[3]=2
的情况下不起作用,但适用于所有其他情况:例如: x[4]=2
或x[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)
因此引发异常,但一切都在被捕获之前完成。在终止流程之前有没有办法让它被抓住?
答案 0 :(得分:1)
您只能捕获引发的异常。无效的指针访问不会引发异常,它只会导致未定义的行为,并且在您的特定情况下会导致堆栈转储。
如果您想了解这种情况,请使用std::vector
和at
function来访问相关项目。当与无效索引一起使用时,这将抛出std::out_of_range
。但是,通常最好避免这种访问先验的可能性,因为它们通常表示程序中存在错误,并且不应通过异常处理错误,应将其从代码中删除。
答案 1 :(得分:1)
在Linux核心转储上由信号处理程序生成,默认操作设置为core
(SIGABRT
,SIGSEGV
,...)。如果要避免核心转储,可以始终捕获/忽略这些信号。它也适用于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();
}