Программа заканчивается сообщением об ошибке abort() на VS2017
Ниже код выходит из-за ошибки
msgstr "abort () был вызван".
Это из-за исключения броска деструктора? Я знаю, что исключение из деструктора приводит к неопределенному поведению, но есть и контраргументы. и более того, эта же программа работает правильно в VS 2012.
#include "stdafx.h"
#include<iostream>
using namespace std;
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn()
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
throw;
}
}
};
int main()
{
try
{
Txn t;
}
catch (int i)
{
cout << "Exception" << i << endl;
}
return 0;
}
В примечаниях к выпуску VS2017 ничего не говорится об изменениях обработки исключений.
Итак, у меня есть следующие вопросы:
- Неправильно ли создавать исключение в деструкторе начиная с VS2017? он всегда будет выходить из программы, вызывая abort()?
- Есть ли флаги, с которыми мы можем заставить его работать?
Пожалуйста, предложите.
3 ответа
Проблема здесь в том, что все деструкторы по умолчанию noexcept(true)
, Бросок исключения без изменения звонка std::terminate
немедленно. Если мы используем
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn() noexcept(false)
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
throw;
}
}
};
int main()
{
try
{
Txn t;
}
catch (int i)
{
cout << "Exception" << i << endl;
}
return 0;
}
Программа работает как положено.
Причина, по которой это работало в VS2012, но не в VS2017, заключается в том, что до C++11 деструктор мог выдавать без необходимости его указания. С С ++ 11 noexcept
Спецификаторы и изменение, что все деструкторы noexcept
по умолчанию вызывает его поломку в VS2017.
Деструкторы по умолчанию не генерируют исключения (noexcept
). Вы можете сказать компилятору, что этот деструктор не использует значение по умолчанию, добавив noexcept(false)
,
При попытке этого в этом примере мы теперь получаем другую диагностику от компилятора - деструктор никогда не достигнет конца. Для деструктора нехорошо никогда полностью уничтожать объект...
Чтобы "исправить" это, я должен был сделать условный возврат с if
,
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn() noexcept(false)
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
if (i == 10) throw;
}
}
};
Неопределенное поведение может быть чем угодно, включая вызов abort(); Просто избегайте всего, что может вызвать это.
Бросок из деструктора не запрещен, но выполнение этого внутри try/catch может привести к двойному исключению.