全局对象本质上是不安全的

Global objects are inherently unsafe?

本文关键字:不安全 本质上 对象 全局      更新时间:2023-10-16

我知道在不同的转换单元(例如不同的cpp/lib/dll/so文件)中定义的静态变量的初始化顺序是未定义的。这是否意味着以下程序的行为没有得到很好的定义?

#include <vector>
std::vector<int> v;
int main()
{
    v.push_back(1);
}

编辑:这里我用STL矢量作为一个例子。但它可能是任何其他"第三方"阶级的对象。因此,我们不知道该对象是否通过其他全局变量初始化。这意味着在C++中,即使创建一个具有非平凡构造函数的全局对象也是不安全的。正确的

否,因为当您在main中使用v时,它是完美定义的。静态初始化阶段发生在您在main…中使用v之前。。。

如果在不同的翻译单位中使用两个全局变量,并且两者之间存在依赖关系,就会出现问题。有关解释,请参阅此C++FAQ lite。常见问题解答中的下一项解释了如何避免"惨败"。

静态初始化的问题使C++中的全局变量比任何其他语言中的都糟糕。优秀的库编写人员知道这个问题,并避免了静态订单初始化的惨败。即使没有,如果这个库传播得很好,也会有人发现问题,我希望能解决它。但第三方库并不总是写得很好的,它们可能是由一个无知的C++程序员在你公司写的库。。。

所以,是的,这是不安全的,你是对的。在C++中,避免使用全局变量甚至比在其他语言中还要多!

注:Columbo指出,标准并没有确切地说v是在进入main之前定义的(见他的回答)。在你的例子中没有实际的区别。

它在[basic.start.init]/4:中指定

它是由实现定义的具有静态存储持续时间的非局部变量在主语句的第一个语句。如果初始化推迟到在main的第一个语句之后的时间点,它应发生在中定义的任何函数或变量的第一次odr使用(3.2)与要初始化的变量相同的转换单元。

因此,定义了v在第一次用于该翻译单元的任何功能(包括main)之前被初始化。这意味着在该特定程序中vmain的第一语句之前被初始化

不同翻译单元中的多个变量取决于它们的相对初始化顺序时,就会发生静态初始化顺序惨败;根据它们的初始化,初始化可以相对于彼此不确定地排序。

由于只定义了一个全局对象,因此其初始化只能有一个顺序,因此没有问题。