全局对象本质上是不安全的
Global objects are inherently unsafe?
我知道在不同的转换单元(例如不同的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
)之前被初始化。这意味着在该特定程序中v
在main
的第一语句之前被初始化
当不同翻译单元中的多个变量取决于它们的相对初始化顺序时,就会发生静态初始化顺序惨败;根据它们的初始化,初始化可以相对于彼此不确定地排序。
由于只定义了一个全局对象,因此其初始化只能有一个顺序,因此没有问题。
- 这些是什么样的错误?即使我不在 Linux 上工作,我也遇到了 Linux 错误
- c++ AVX512 本质上等价于 _mm256_broadcast_ss()?
- C++/CLI 和 C#/VB 与不安全和外部有什么区别?
- "new"创建的实例的所有成员变量是否都存在于堆上而不是堆栈上?
- 问:Apache Arrow 数组生成器不安全追加
- 不安全的 MPI 非阻塞通信示例?
- 有没有一种简单的方法来检查C++中的不安全表达式
- 不在 VS 上运行,但在开发C++上运行
- 为什么静态向下转换unique_ptr不安全?
- 哪些整数操作不安全
- 编译器在 const ref 类型参数上使用临时对象时是否应该警告不安全的行为?
- 为什么序列化指令本质上是不友好的
- std::atomic_compare_exchange_weak线程在设计上是否不安全
- 全局对象本质上是不安全的
- std::map上可能存在线程不安全操作
- 在同一个vtkSmartPointer上调用new两次是不安全的吗?
- 共享指针本质上不强制转换为基/派生类型
- 在哪些体系结构上计算无效指针不安全
- boost条件不在具有两个生产者和一个消费者的线程安全队列上工作
- C++的默认复制构造函数本质上是不安全的吗?迭代器从根本上也是不安全的吗?