块范围静态的析构函数可以被调用几次? [英] Destructors of block-scope statics can be called several times?

查看:217
本文介绍了块范围静态的析构函数可以被调用几次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚读了这篇文章,介绍了目前 boost :: mutex 实现并注意到以下短语:


额外的问题潜在的竞争
条件第一次通过,这可能导致
析构函数在流行的编译器上运行多次,这是
未定义的行为 - 编译器经常使用相当于调用
atexit,以确保以相反的
顺序进行销毁,并且可能导致
构造函数运行两次的初始化比赛也可能导致析构函数是
注册两次


是真的吗?我应该真正检查是否另一个线程已经在这个对象的析构函数通过原子操作或这样的东西?我应该做它甚至在C ++ 11 - C ++ 14?因为据我所知,没有更多的静态存储持续时间的同一本地对象的构造函数可以从几个线程同时调用问题,因为C ++ 11 - 它要求另一个线程应该等待构造函数的完成。我是对吗?

解决方案

看起来这篇文章是在C ++ 11之前编写的, p ...

<...>


$ b $ b

这是C ++ 11之前的情况,它没有指定在这种情况下发生了什么,因为线程不是内存模型pre C ++ 11的一部分。



这在C ++ 11和草案C ++ 11标准部分 6.7 声明语句> ):


所有块范围变量的零初始化
存储持续时间
(3.7.1)或线程存储持续时间(3.7.2)是在执行任何其他初始化之前执行的
。 [...]否则
这样的变量初始化时第一次控制通过
它的声明;这样的变量被认为在
完成其初始化时被初始化。如果初始化由
抛出异常,则初始化不完成,因此在下一次控制进入声明时将再次尝试
如果
控制在初始化变量
的同时输入声明,并发执行将等待初始化的完成
[...] p>

Pre C ++ 11我们必须像处理任何其他临界区一样对待静态局部变量。我们可以找到一个很好的描述情况pre C ++ 11在后 C ++ scoped静态初始化不是线程安全的,有意义!


I just read this article about the actual reasons behind the current boost::mutex implementation and noticed the following phrase:

Block-scope statics have the additional problem of a potential race condition on "the first time through", which can lead to the destructor being run multiple times on popular compilers, which is undefined behaviour — compilers often use the equivalent of a call to atexit in order to ensure that destruction is done in the reverse order of construction, and the initialization race that may cause the constructor to be run twice may also cause the destructor to be registered twice

Is it true? Should I really check whether another thread already inside this object's destructor via atomic operations or something like this? Should I do it even in C++11 - C++14? Because as far as I know there's no more "constructor for the same local object with static storage duration can be called simultaneously from several threads" problem since C++11 -- it requires that another threads should wait for the constructor's completion. Am I right?

解决方案

It looks like this article was written pre C++11, it says amongst other things:

[...] next version of the C++ Standard, scheduled to be released in 2009.[...]

and this was the case pre C++11, it was unspecified what happened in this case since threading was not part of memory model pre C++11.

This changed in C++11 and the draft C++11 standard section 6.7 Declaration statement says (emphasis mine):

The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization takes place. [...] Otherwise such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. [...]

Pre C++11 we have to treat the static local variable just like we treat any other critical section. We can find a excellent description of the situation pre C++11 in the post C++ scoped static initialization is not thread-safe, on purpose!.

这篇关于块范围静态的析构函数可以被调用几次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆