问题标签 [static-order-fiasco]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
12 回答
58558 浏览

c++ - 查找 C++ 静态初始化顺序问题

我们在静态初始化命令 fiasco中遇到了一些问题,我正在寻找方法来梳理大量代码以查找可能出现的情况。关于如何有效地做到这一点的任何建议?

编辑:关于如何解决静态初始化顺序问题,我得到了一些很好的答案,但这不是我的问题。我想知道如何查找受此问题影响的对象。在这方面,埃文的回答似乎是迄今为止最好的;我不认为我们可以使用 valgrind,但我们可能有可以执行类似功能的内存分析工具。这只会在给定构建的初始化顺序错误的情况下发现问题,并且顺序可以随着每次构建而改变。也许有一个静态分析工具可以捕捉到这一点。我们的平台是在 AIX 上运行的 IBM XLC/C++ 编译器。

0 投票
6 回答
56629 浏览

c++ - C++ 静态初始化顺序

当我在 C++ 中使用静态变量时,我经常想要初始化一个变量,然后将另一个变量传递给它的构造函数。换句话说,我想创建相互依赖的静态实例。

在单个 .cpp 或 .h 文件中,这不是问题:实例将按照它们声明的顺序创建。但是,当您想用另一个编译单元中的实例初始化静态实例时,似乎无法指定顺序。结果是,根据天气情况,可能会构建依赖于另一个实例的实例,然后才构建另一个实例。结果是第一个实例初始化不正确。

有谁知道如何确保以正确的顺序创建静态对象?我已经搜索了很长时间的解决方案,尝试了所有解决方案(包括 Schwarz Counter 解决方案),但我开始怀疑是否有一个真正有效的解决方案。

一种可能性是使用静态函数成员的技巧:

确实,这确实有效。遗憾的是,您必须编写 globalObject().MemberFunction(),而不是 globalObject.MemberFunction(),导致客户端代码有些混乱和不雅。

更新:感谢您的反应。遗憾的是,似乎我确实已经回答了我自己的问题。我想我得学会忍受它...

0 投票
2 回答
13091 浏览

c++ - 初始化嵌入在静态库中的 qt 资源

我有下一个情况:我需要在独立静态库中创建小部件,然后将其与最终应用程序(visual c++ 9.0,qt 4.5)链接。这个静态小部件库包含一些资源(图标),并由几个 .cpp 文件组成(每个文件都包含独立的小部件)。据我所知,如果我在静态库中使用它们(资源),我必须初始化 qt 资源系统,并调用“Q_INIT_RESOURCE(resource_file_name)”。我用下一个代码解决了这个问题(在静态库中的每个 .cpp 文件中):

我没有使用第一种方法,而是在静态库项目中使用初始化代码创建了单独的 init.cpp 文件(以避免在每个 .cpp 文件中包含初始化代码),但这不起作用。

为什么这不起作用?

这种使用 StaticLibInitializer 的方法在各种编译器和平台之间是否安全且可移植?

0 投票
3 回答
2286 浏览

c++ - 在 C++ 中重现静态初始化顺序惨败

我读到了 C++ 中与应用程序崩溃相关的静态初始化顺序惨败。我想我明白了,但仍然有几个问题:
1)如果我想重现这个问题,我该怎么做(这样我的程序就会崩溃)?我想编写一个测试程序来重现崩溃。如果可以的话,能否提供一下源代码?
2)我阅读了这篇C++ FAQ Lite文章,它说它在两个不同的文件中有两个静态对象 x 和 y,并且 y 调用 x 的方法。作为全局静态成员,它如何具有文件级范围?
3)这个问题非常危险,有没有尝试在编译器级别修复它?
4) C++ 专家在实际生产中遇到过多少次这个问题?

0 投票
4 回答
16010 浏览

c++ - 静态初始化命令惨败

我正在从一本书中阅读有关 SIOF 的信息,它举了一个例子:

现在我的问题是:
在上面的代码中,会发生以下事情吗?

  1. 在编译file1.cpp 时,编译器将y 保留原样,即不为其分配存储空间。
  2. 编译器为 x 分配存储空间,但不初始化它。
  3. 在编译file2.cpp 时,编译器将x 保留原样,即不为其分配存储空间。
  4. 编译器为 y 分配存储空间,但不初始化它。
  5. 在链接 file1.o 和 file2.o 时,现在让 file2.o 先初始化,所以现在:
    x 的初始值是否为 0?还是没有初始化?
0 投票
5 回答
3039 浏览

c++ - 静态初始化命令惨败

在他的“Thinking in C++”(第 10 章)中,Eckel 描述了一种由 Jerry Schwarz 开创的用于解决惨败的技术。他说,如果我们想将x初始化为 100 并将y初始化为 200 并在所有翻译单元之间共享它们,我们将创建一个如下所示的 Initializer.h:

在实现文件中,我们有

并且 Eckel 说“静态初始化(在实现文件中)将强制所有这些值为零”。

让我考虑以下情况:编译器在包含该标头的某个其他文件之后处理实现文件(这意味着 x 和 y 在该其他文件中已设置为 100 和 200)。编译器看到int x了,那么它会做什么呢?它会将 x 和 y 设置为零,从而消除初始化和以前文件中所有可能的更改吗?但如果确实如此,那么initCount也将被设置为零,从而破坏整个技术。

0 投票
3 回答
1516 浏览

c++ - C++ 库中静态 STL 容器的双重初始化

关于“静态初始化顺序惨败”,这里有一些很好的问题和答案,但我似乎遇到了它的另一种表达方式,特别丑陋,因为它不会崩溃但会丢失和泄漏数据。

我有一个自定义 C++ 库和一个链接到它的应用程序。库中有一个静态 STL 容器,用于注册类的所有实例。这些实例恰好是应用程序中的静态变量。

由于“惨败”(我相信),我们在应用程序初始化期间让容器充满了应用程序实例,然后库开始初始化并且容器被重置(可能泄漏内存),最终只有来自的实例图书馆。

这就是我用简化代码复制它的方式:

mylib.hpp:

mylib.cpp:

我的应用程序.cpp:

编译对象:

运行 myapp1:

运行 myapp2:

问题来了,静态向量是重新初始化的,还是在初始化之前使用的?这是预期的行为吗?

如果我将库“ar”为“mylib.a”(ar rcs mylib.a mylib.o),则问题不会发生,但可能是因为只有一个有效的订单可以链接到 .a,而且它是通过图书馆在最后,至于 myapp1 这里。

但是在我们的实际应用程序中,一个包含许多目标文件和一些静态 (.a) 库的更复杂的应用程序共享一些静态注册表,问题正在发生,到目前为止,我们设法解决它的唯一方法是应用'[10.15 ] 如何防止“静态初始化命令惨败”?.

(我仍在研究我们有些复杂的构建系统,看看我们是否正确链接)。

0 投票
2 回答
2419 浏览

c++ - Nifty/Schwarz 计数器,符合标准?

今天早上我和一位同事讨论了静态变量初始化顺序。他提到了Nifty/Schwarz 柜台,我(有点)困惑。我了解它是如何工作的,但我不确定这在技术上是否符合标准。

假设以下 3 个文件(前两个是从More C++ Idioms复制粘贴的):





...这就是问题所在!有两个静态变量:

  1. “漂亮的计数器”在Stream.cpp;和
  2. 中的“初始化程序” Program.cpp

由于这两个变量恰好位于两个不同的编译单元中,因此没有(AFAIK)官方保证在调用构造函数nifty_counter之前初始化为 0 。initializer

我可以将两个快速解决方案视为“有效”的两个原因:

  1. 现代编译器足够聪明,可以解决两个变量之间的依赖关系,并将代码以适当的顺序放置在可执行文件中(极不可能);
  2. nifty_counter实际上就像文章所说的那样在“加载时”初始化,并且它的值已经放在可执行文件的“数据段”中,所以它总是在“任何代码运行之前”被初始化(很有可能)。

在我看来,这两者都依赖于一些非官方但可能的实现。这个标准是否符合标准,或者这只是“很可能起作用”以至于我们不应该担心它?

0 投票
2 回答
167 浏览

c++ - 此代码会产生未定义的行为还是仅仅是未指定的行为?

假设我们有两个编译单元,如下所示:

当我在 VC2010 上尝试它时,它首先初始化value1value2归零。两者都不是动态初始化的value1value2默认初始化不适用于它们吗?

谢谢,

0 投票
11 回答
1898 浏览

java - Java有静态订单初始化惨败吗?

这里的一个最近的问题有以下代码(嗯,类似于这个)来实现一个没有同步的单例。

现在,我想明白这是在做什么。由于实例是static final,它是在任何线程调用之前很久就构建的,getInstance()因此不需要同步。

仅当两个线程尝试同时调用时才需要同步getInstance()(并且该方法在第一次调用而不是"static final"同时进行构造)。

因此,我的问题基本上是:为什么你会更喜欢单例的惰性构造,例如:

我唯一的想法是,使用该static final方法可能会引入排序问题,就像 C++ 静态初始化顺序惨败一样。

首先,Java真的这个问题吗?我知道类中的顺序完全指定的,但它是否以某种方式保证类之间的顺序一致(例如使用类加载器)?

其次,如果顺序一致的,为什么惰性构造选项会有优势?