Я столкнулся с проблемой при использовании Visual Studio 15 для компиляции. Этот код иллюстрирует ее:

const char* getx() { return "foo"; }

void __declspec(naked) nf()
{
    static const char* x = getx();
}

При этом возникает следующая ошибка: Ошибка C3068 'nf': 'голая' функция не может содержать объекты, которые потребуют разворачивания, если произойдет исключение C++. Я не очень понимаю, почему это не работает; статические объекты не являются автоматическими, и в плане хранения они ведут себя более или менее как глобалы и инициализируются до выполнения точки входа (насколько я понимаю). Если это так, то о каком разворачивании идет речь в этом сообщении? На стеке в этот момент ничего нет, поэтому разматывать нечего. Кроме того, если я удалю вызов функции, объявление переменной static будет в порядке (как и вызов функции без присваивания или присвоение переменной x постоянного значения, например, static const char* x = 0;).

Я что-то упускаю?

user4520

Ответы (2)

Атрибут функции noexcept, введенный в C++11, формально заявляет, что функция не выбрасывает исключения.

Несмотря на то, что из getx() не может быть исключений, компилятор не будет автоматически добавлять атрибут noexcept, поскольку это изменяет сигнатуру функции.

После этого, когда компилятор разбирает функцию nf(), он видит вызов другой функции, которая может вызвать исключение, что, очевидно, запрещено в "голой" функции, специфичной для вашей платформы.

Явное объявление getx как noexcept явно декларирует, что эта функция не выбрасывает исключение, поэтому компилятор будет знать, что этот вызов функции не выбросит исключение, и позволит "голой" функции скомпилироваться.

Подробности из комментариев:

Статическая переменная должна быть инициализирована один раз и только один раз. И это также должно быть выполнено потокобезопасным способом.

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

Для корректной работы этой функции требуется некоторый (неуказанный) механизм, специфичный для реализации. Очевидно, это противоречит тому, чтобы сделать функцию "голой".

2022 WebDevInsider