стандарте написано "If an exception is thrown during the destruction of temporaries or local variables for a return statement ([stmt.return]), the destructor for the returned object (if any) is also invoked"
https://godbolt.org/z/9E587deEf
https://eel.is/c++draft/except.ctor#2
Видимо, потому что RVO... ( код даже не смотрел)
rvo отключено через -fno-elide-constructors
Ну и вызываются только деструкторы тех объектов, которые был СКОНСТРУИРОВАНЫ, причём, полностью.
return S{3}; // а не {3}
развернёте ответ? пока не очень понял
там где оно отключено всё четко вызывается
https://godbolt.org/z/hn3Ec58YK
T S(3) ~T catch S(4) S(S& = 4) ~S(4) -- ~S(4) у меня такой вывод с отключённым рво, а у вас?
ага а можете, пож, объяснить, почему так?
а как может позваться деструктор локального объекта во время конструирования возвращаемого? (вывод в консоль из констуктора возвращаемого произошёл)
возвращаемый объект сконструирован к моменту вызова деструкторов локальных объектов
Так у тебя там вообще, исключение в деструкторе...
стандартом это не запрещено, если я правильно понял
этот пример, если что - повторение Note из стандарта
Ну да, но terminate вызывать будет. https://en.cppreference.com/w/cpp/error/terminate А терминате - аборт. https://en.cppreference.com/w/cpp/utility/program/abort А он деструкторы не зовёт
terminate вызвать не будет, деструктор определён как noexcept(false)
terminate не вызывается -> abort не вызывается -> выполнение продолжается -> должен позваться деструктор возвращаемого объекта, но не зовётся
Бросать исключения из деструктора можно, если пометить его noexcept(false)
И если его бросаешь, вызывается terminate
Правильно, если его не поймаешь...
вот про терминейт "Whenever an exception is thrown and the search for a handler ([except.handle]) encounters the outermost block of a function with a non-throwing exception specification" https://eel.is/c++draft/except.spec#5
gcc, смотрю, ведет себя точно так же msvc пробовали?
msvc под рукой нет, а годболт его пока не умеет запускать)
19.30.30423 (vs 2022 preview 3) T S(3) ~T catch S(4) -- ~S(4)
У вас в правой вкладке, где вы компилируете с 17 стандартом рво не отключен и работает. Другое дело что такой сайд-эффект от рво выглядит как баг.
да, правая вкладка была сначала, потом я левую сделал с отключением рво, пардон за неоднозначность
хм! я, правда, очень сомневаюсь, что баг сразу в трёх главных компиляторах, скорее это я чё-то проморгал, но вот пока не могу понять, что)
Да, я глянул оригинальный годболт и понял, сорян. return {3} это initilizer_list видимо по какойто причине это ломает лайфтайм возвращаемому объекту и не генерит вызов деструктора. Но выглядит как баг честно говоря, мне не приходит в голову что в стандарте это нарушает. Если явно сконструировать тип return S{3} и вырубить rvo то все выглядит корректно, но рво один хрен не должно менять поведение.
Можно и моё любопытство удовлетворить? Зачем ты бросаешь исключение в деструкторе?
однако пока что ничто не опровергает тот пункт, который вы привели в самом начале
пожалуйста, перестаньте мучить человека этим левым вопросом. там все хорошо с выборосом исключения, и пример этот из стандарта
конечно! я набрёл на этот пример в стандарте. там искл бросается, потому что это пример, иллюстрирующий пункт "шо там с деструкциями при исключении в деструкторе")
Ну ок, я просто спросил...
спасибо за поддержку!
ноль проблем, ответил)
Да, еслиб не он, я б тебя уже съел...
Во всех вариациях теряется один вызов деструктора. В том числе при явном конструировании объекта S{3}: после него происходит копирование и деструктор вызывается лишь на одном объекте.
я не знаю, как можно обойти такую четкую формулировку, еще и с примером http://eel.is/c++draft/except.ctor#2.sentence-2 а то, что основные имплементации отлично умеют ошибаться, мы уже проходили с constant evaluation. по-моему, все вместе в том числе
Да, точно. Проглядел конструктор копирования.
в общем, это действительно баги в компиляторах, причем старые. пишут, что в gcc исправили, но пример из стандарта по-прежнему работает неправильно https://bugs.llvm.org/show_bug.cgi?id=13505 https://bugs.llvm.org/show_bug.cgi?id=12286 https://bugs.llvm.org/show_bug.cgi?id=12286#c4 это я вычитал здесь, а потом нашел в багтрекере: Clause 18.2.2. requires local temporaries, such as return values, to have their destructors called when unwinding. However, clang’s existing exception implementation does not conform to this part of the specification
тоже не поможет, вызовется конструктор копии и у нас будет уже 2 объекта, и соответственно должно быть 2 деструктора, но он почему-то один вызывается
Обсуждают сегодня