Многие виды UB вызывают ворнинги в GCC и Clang.
Кстати, сейчас для определения UB во многих случаях можно писать constexpr-функции. По новому Стандарту UB недопустим в constexpr-функциях, поэтому код не скомпилируется.
Спасибо за лестный отзыв!
Я стараюсь писать о чём-то новом (в том числе и для себя), а не переписывать одно и то же другими словами. Но если узнаю что-то действительно новое про UB — постараюсь написать и об этом.
Я в курсе про точки следования (как они назывались до C++11, кстати), спасибо.
> Дело в том, что описания UB как раз отсутствуют в Стандарте.
Не согласен. Как раз именно в Стандарте все неопределённые ситуации и описаны в терминах UndB, UnspB и IDB. И все определения там есть, в самом начале.
Автор решил не приводить примеры неопределённого поведения, т.к. они подробно разжёваны, в том числе и на этом сайте. Автор всего лишь попытался показать разницу между undefined и unspecified behavior, о чём честно сказал в первом абзаце.
P.S.: я кстати не понял, где там в примере Unspecified behavior? a == 1, c == 0. Разве нет?
Вызывать виртуальные функции из конструктора и деструктора вообще нельзя (вызов ведёт на ещё не построенный или уже разрушенный «верхний этаж»).
Не ведёт, т.к. применяется статическое связывание вместо динамического. Это уже обсуждалось в комментариях выше.
Хотя, в целом скорее соглашусь — проблема не завязана только на треды. Я лишь описываю достаточно типичный случай, когда с этой проблемой можно столкнуться, используя треды.
Честно говоря, не очень понял. В общем случае если вызвать виртуальный метод из конструктора, будет просто применено статическое связывание вместо динамического. В данном же случае вызывается именно run() из производного класса, что и приводит к проблемам.
Если я что-то не понял в комментарии, поясните пожалуйста.
Я представил самый простой вариант. Честно говоря, изначально в статье был ещё вариант с запуском треда и ожиданием на condition_variable, но я не увидел у него преимуществ по сравнению с обычной двухфазной инициализацией и удалил.
Всё зависит от того, насколько часто вы читаете Стандарт, и как часто сообщения компилятора ставят вас в тупик. Если редко, то наверно необходимости особой нет. А, ну ещё вариант — если вы разрабатываете компилятор — тогда точно необходимо. :)
Первая часть статьи вводит в проблему, так сказать, рассматривает стандартные подходы и показывает, почему они не решают всех проблем. Кому-то это может быть очевидным, кто-то найдёт что-то новое для себя.
Что касается std::nested_exception — я рассматривал и их, но там всё же несколько про другое. Я думал некоторое время над тем, как решить проблему обработки множественных исключений, прилетающих из библиотечного кода, с помощью std::nested_exception, но придумать не смог. Этот механизм требует всё же изначально выбрасывать исключения не совсем стандартным способом. Если вам известно, как можно приспособить этот механизм для обсуждаемых в статье примеров, мне будет очень интересно его увидеть.
Кстати, сейчас для определения UB во многих случаях можно писать constexpr-функции. По новому Стандарту UB недопустим в constexpr-функциях, поэтому код не скомпилируется.
Я стараюсь писать о чём-то новом (в том числе и для себя), а не переписывать одно и то же другими словами. Но если узнаю что-то действительно новое про UB — постараюсь написать и об этом.
> Дело в том, что описания UB как раз отсутствуют в Стандарте.
Не согласен. Как раз именно в Стандарте все неопределённые ситуации и описаны в терминах UndB, UnspB и IDB. И все определения там есть, в самом начале.
P.S.: я кстати не понял, где там в примере Unspecified behavior? a == 1, c == 0. Разве нет?
Не ведёт, т.к. применяется статическое связывание вместо динамического. Это уже обсуждалось в комментариях выше.
Хотя, в целом скорее соглашусь — проблема не завязана только на треды. Я лишь описываю достаточно типичный случай, когда с этой проблемой можно столкнуться, используя треды.
Если я что-то не понял в комментарии, поясните пожалуйста.
Что касается std::nested_exception — я рассматривал и их, но там всё же несколько про другое. Я думал некоторое время над тем, как решить проблему обработки множественных исключений, прилетающих из библиотечного кода, с помощью std::nested_exception, но придумать не смог. Этот механизм требует всё же изначально выбрасывать исключения не совсем стандартным способом. Если вам известно, как можно приспособить этот механизм для обсуждаемых в статье примеров, мне будет очень интересно его увидеть.