В приведенном ниже коде я использую try/catch
в коде модуля Python. в try
Блок у меня есть простая ошибка (нарушение доступа к памяти) и пытается перехватить соответствующее исключение и тихо завершить программу без генерации .stackdump
файл. Однако последнее все еще генерируется, что подразумевает, что try/catch
конструкция не делает свою работу. Как я могу избежать генерации .stackdump
файл и выход из программы без ошибок, когда неправильная операция (как в коде) встречается?
Постскриптум я компилирую код в cygwin с помощью 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)
;
}
РЕДАКТИРОВАТЬ:
В соответствии с тем, что Мацек предложил, я попробовал следующий трюк:
Сделайте функцию обработки сигналов для выдачи исключения, но не выхода
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::vector
и at
функция чтобы получить доступ к элементам. Это бросит std::out_of_range
при использовании с неверным индексом. Однако, как правило, лучше избегать возможности такого доступа априори, поскольку они обычно указывают на ошибку в вашей программе, и ошибки не должны обрабатываться с помощью исключений, их следует удалять из кода.
В 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();
}