C++ 是否未指定构成块作用域静态变量或线程存储持续时间变量初始化失败的因素?

C++ 是否未指定构成块作用域静态变量或线程存储持续时间变量初始化失败的因素?,c++,c++11,language-lawyer,static-initialization,C++,C++11,Language Lawyer,Static Initialization,在回答了问题后,在标准试卷中没有找到令人满意的答案,我开始怀疑。本标准规定了上述变量的以下w.r.t.初始化: §6.7[stmt.dcl]p4 […]否则,在控件第一次通过其声明时初始化该变量此类变量在初始化完成时被视为已初始化。如果初始化通过抛出异常退出,则初始化未完成,因此下次控件进入声明时将再次尝试初始化 除了抛出异常(longjmp() 我是否忽略了标准中的任何内容?我一遍又一遍地查看初始化、声明和异常条款,甚至还快速搜索了“static”,但找不到任何相关的内容 这是标准中的不足之

在回答了问题后,在标准试卷中没有找到令人满意的答案,我开始怀疑。本标准规定了上述变量的以下w.r.t.初始化:

§6.7[stmt.dcl]p4

[…]否则,在控件第一次通过其声明时初始化该变量此类变量在初始化完成时被视为已初始化。如果初始化通过抛出异常退出,则初始化未完成,因此下次控件进入声明时将再次尝试初始化

除了抛出异常(
longjmp()

我是否忽略了标准中的任何内容?我一遍又一遍地查看初始化、声明和异常条款,甚至还快速搜索了“static”,但找不到任何相关的内容


<强>这是标准中的不足之处(并且是这样的缺陷)?>/P>> P> C++规范只能定义包含在C++规范中的东西。记住:C++规范定义了它定义的虚拟机的行为。如果它没有定义某些事情可能发生,它肯定不会定义C++的行为,而它并没有说它可能发生。

根据C++规范,线程可以以三种方式退出:通过从其主函数返回,通过其主要函数抛出异常,并直接退出(如<>代码> STD::终止< /代码>或类似函数)。简而言之,C++线程不能以任何其他方式退出。在标准C++中没有<代码> ExtType < /Cuff>函数。类似地,

std::thread
无法从外部或内部终止线程

<>所以,任何导致C++所说不能发生的事情都是定义不明确的。我猜这甚至不是“未定义的行为”;在C++11真正确定线程交互如何工作之前,线程就处在这个模糊的空间中

“信号”也是如此,不管是什么。C++规范没有说明这些函数会导致函数退出。这里有龙

至于
longjmp
,这是由
longjmp
的行为所涵盖的。当您使用
longjmp
退出函数时,该函数从未完成,就像您使用
throw
catch
一样。在C++中,对象仅在构造函数完成后才构建。因此,对象的初始化从未完成,并且未初始化

<>我没有ISO规范(C++代码引用了< C++ > LangJMP < /C> >的行为),但是C++ 11强烈建议您可以在<未定义的行为:

时,将<代码>抛出>代码> >代码> catch <代码> > <代码>
§18.10 [support.runtime] p4:
函数签名longjmp(jmp_buf jbuf,int val)在本国际标准中具有更严格的行为。如果通过catch和throw替换setjmp和longjmp将调用任何自动对象的非平凡析构函数,则setjmp/longjmp调用对具有未定义的行为


所以我不认为这是不够具体的。它可能没有很好和整洁的布局,但所有的部分都在那里。

仅仅因为文本提到了一个特定的案例,并不意味着遗漏其他案例会有任何不同。如果有其他方法阻止初始化完成,则实现必须在下一次执行时重试


我认为Nicol的答案基本上是正确的,但非平凡构造函数并不意味着非平凡析构函数<因此,code>longjmp
可能会中断初始化,因此必须重试。这仅在多线程环境中是很棘手的,因为在多线程环境中,需要一个互斥体来防止线程之间的竞争条件,线程争先恐后地执行初始化。幻象互斥对象需要一个非平凡的析构函数,即使初始化的对象没有析构函数。可能的结果是僵局。这可能是一个好的材料,对于博士

C++是否定义了与信号有关的任何东西?还是
longjmp
?线程退出可能会改变一些事情。您是否有任何具体的场景,您认为标准没有充分规定这些场景?@Kerrek:链接的问题:P@Lightness:18.10/4用于
setjmp
/
longjmp
。另见:@Xeo:Hmm。。。我不太明白这个问题有什么模棱两可的地方。您是否可以详细解释一下,为什么您认为该行为没有得到充分的详细说明?标准并不是只列出一种情况,而是只指定了该情况下的重试。它没有说“如果失败,请下次重试”。它特别指出“如果抛出失败,请下次重试”。@Xeo:一点也不。如果初始化没有完成,那么它一开始就不是初始化。重试是第一次。前面的文本已经暗示了这一点,这一点通过语言“初始化未完成,因此将再次尝试……”不,没有,因为前面的文本只提到例外。你不能同时拆下两部分。无论如何,我认为这至少是一个澄清的好人选。顺便说一句,在互斥问题上,我认为第138页上的这句话可能适用:“88)实现不能在初始值设定项的执行周围引入任何死锁。”@Xeo:我省略的那句话当然是指例外情况。之前的案文没有提到例外情况。重试初始化的行为完全由“否则在控件第一次通过其声明时初始化此变量;考虑此变量