我在使用Visual Studio 15编译时遇到了问题。这段代码说明了这一点:
const char* getx() { return "foo"; }
void __declspec(naked) nf()
{
static const char* x = getx();
}
此操作失败,并显示以下错误:Error C3068 'nf': a 'naked' function cannot contain objects that would require unwinding if a C++ exception occurred
。不过,我真的不明白为什么会失败;静态对象不是自动的,就存储而言,它们的行为或多或少类似于全局变量,并且在执行入口点之前被初始化(据我所知)。如果是这样,那么这条消息指的是什么?此时堆栈中什么也没有,所以没什么可放松的。另外,如果我删除函数调用,static
变量声明就可以了(没有赋值的函数调用,或者为x
变量赋值,例如static const char* x = 0;
)
我在这里遗漏了什么吗?
答案 0 :(得分:1)
从评论中综合:
静态变量必须初始化一次,并且只能初始化一次。而这也必须以线程安全的方式执行。
这里的一个问题是,如果初始化因异常而失败,则该变量仍然未初始化,并且下次调用该函数时,必须执行另一次初始化。
这需要一些(未指定的)特定于实现的机制才能正常工作。显然它与使这个功能“裸露”相冲突。
答案 1 :(得分:1)
C ++ 11中引入的noexcept
函数属性正式声明该函数不会抛出异常。
即使getx()没有抛出任何异常,编译器也不会自动添加noexcept
属性,因为这会更改函数签名。
因此,当编译器解析nf()
函数时,它会看到对另一个可能抛出异常的函数的调用,这显然是在特定于平台的“裸”函数中被禁止的。
明确声明getx
为noexcept
显式声明此函数不会抛出异常,因此编译器会知道此函数调用不会抛出异常,并允许“裸”函数编译