Что такое исключение "recursive_init_error"? - PullRequest
8 голосов
/ 06 августа 2011

Я решил сделать тест с вычисленным gotos и локальной статикой

void g() { std::cout << "init "; } 
void f() { 
  int z = 0; 
  y: z++; 
  static int x = 
    (g(), z == 1 ? ({ goto *&&y; 0; }) : 0); 
}

int main() { f(); std::cout << "!"; f(); }

Я хотел посмотреть, будет ли вывод «init init!». Но, к моему удивлению, я не получил этот вывод, а вместо этого GCC обработал его изящно, выдав во время выполнения:

init terminated by recursive_init_error: exception

Что это за исключение? Это стандартное исключение? C ++ 03 или C ++ 0x? Спасибо за любые объяснения.

1 Ответ

16 голосов
/ 06 августа 2011

Это вызвано тем, что указано в C ++ 03 §6.7 / 4:

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

int foo(int i)
{
  static int s = foo(2*i);    // recursive call – undefined
  return i+1;
}

- конец примера]

В этом случае GCC выдает исключение.Вот некоторая документация об этом.


Обновление C ++ 11: Следующая формулировка была добавлена ​​в C ++ 11, непосредственно перед текстом о рекурсивном случае:

Если элемент управления вводит объявление одновременно с инициализацией переменной, параллельное выполнение должно ожидать завершения инициализации. 88

88 Реализация не должна вводить какие-либо тупики вокруг выполнения инициализатора.

Не меняет проблему здесь, но делает эту конструкцию поточно-безопасной, когда нет рекурсии.

...