Что является неудачной инициализацией статических переменных области действия блока или переменных длительности хранения потока? - PullRequest
7 голосов
/ 30 января 2012

После ответа на этот вопрос и не найдя удовлетворительного ответа в стандартной статье, я начал задаваться вопросом.Стандарт устанавливает следующую инициализацию упомянутых переменных:

§6.7 [stmt.dcl] p4

[...] В противном случае такая переменная инициализируется при первом прохождении контроля через ее объявление; такая переменная считается инициализированной по завершении ее инициализации .Если инициализация завершается с помощью исключения, инициализация не завершена, поэтому она будет повторена при следующем входе элемента управления в объявление.

Нет упоминаний о том, что может привести к инициализацииповторная попытка, если произошел сбой из-за чего-то другого, кроме выдачи исключения (longjmp(), thead exit, несколько имен).

Я пропустил что-либо в стандарте?Я просматривал пункты инициализации, объявления и исключения снова и снова и даже советовался с таблицей содержания CWG дефектов с быстрым поиском «статического», но не смог найти ничего связанного.

Является ли это занижением (и как таковым дефектом) в стандарте?

Ответы [ 2 ]

2 голосов
/ 30 января 2012

Спецификация C ++ может определять только то, что содержится в спецификации C ++.Помните: спецификация C ++ определяет поведение виртуальной машины, которую она определяет.И если он не определяет, что что-то может произойти, он, безусловно, не определяет поведение C ++ вокруг того, что может произойти то, чего он не говорит.

В соответствии со спецификацией C ++ поток может выйтировно тремя способами: путем возврата из своей основной функции, выдачи исключения через его основную функцию и непосредственного выхода из процесса (как в случае std::terminate или аналогичных функций).Короче говоря, поток C ++ не может завершиться любым другим способом.В стандарте C ++ нет функции ExitThread.Точно так же std::thread не может уничтожить поток, ни внешне, ни внутренне.

Следовательно, все, что вызывает то, что, по словам C ++, не может произойти, по определению не определено.Я предполагаю, что это даже не было бы "неопределенным поведением";это было бы в том туманном пространстве, в котором находились потоки до того, как C ++ 11 фактически установил, как взаимодействуют потоки.

То же самое касается "сигналов", какими бы они ни были.Спецификация C ++ не говорит, что они могут привести к закрытию функции.Здесь будут драконы.

Что касается longjmp, это покрыто поведением longjmp.Когда вы используете longjmp для выхода из функции, эта функция никогда не завершается, как если бы вы использовали throw и catch.А в C ++ объект создается только тогда, когда его конструктор завершен.Поэтому инициализация объекта никогда не завершалась, и он не был инициализирован.

У меня нет спецификации ISO C (на которую C ++ ссылается для поведения longjmp), но C ++ 11 настоятельно рекомендует, чтобывы можете приравнять throw / catch к longjmp / setjmp, если вы получаете неопределенное поведение:

§18.10 [support.runtime] p4:

Сигнатура функции longjmp (jmp_buf jbuf, int val) имеет более ограниченное поведение в этом международном стандарте.Пара вызовов setjmp / longjmp имеет неопределенное поведение, если замена setjmp и longjmp на catch и throw вызовет любые нетривиальные деструкторы для любых автоматических объектов.

Так что я не думаю, что это занижено.Это может быть не красиво и аккуратно разложено, но все части есть.

0 голосов
/ 30 января 2012

То, что в тексте упоминается один конкретный случай, не означает, что другие будут другими.Если есть другие способы предотвратить завершение инициализации, реализация должна повториться при следующем выполнении.

Я думаю, что ответ Николя в основном правильный, но нетривиальный конструктор не подразумевает нетривиальный деструктор.longjmp может поэтому прервать инициализацию, так что она должна быть повторена.Это сложно только в многопоточной среде, где необходим мьютекс, чтобы предотвратить состояние гонки между потоками, претендующими первыми выполнить инициализацию.Объекту фантомного мьютекса нужен нетривиальный деструктор, даже если у инициализированного объекта его нет.Вероятный результат - тупик.Это, вероятно, хороший материал для DR.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...