Hap*_*tal 20 c++ dependencies initialization static-order-fiasco
我正在读一本关于SIOF的书,它举了一个例子:
//file1.cpp
extern int y;
int x=y+1;
//file2.cpp
extern int x;
int y=x+1;
Run Code Online (Sandbox Code Playgroud)
现在我的问题是:
在上面的代码中,会发生以下事情吗?
Mic*_*urr 12
初始化步骤在C++标准的3.6.2"非本地对象的初始化"中给出:
第1步:x
与y
任何其他初始化发生之前被初始化为零.
第2步:x
或y
动态初始化 - 标准未指定哪一个.该变量将获得该值,1
因为另一个变量将被零初始化.
第3步:动态初始化另一个变量,获取值2
.
Han*_*ant 11
SIOF非常类似于运行时工件,编译器和链接器与它没有多大关系.考虑atexit()函数,它注册要在程序出口处调用的函数.许多CRT实现具有类似于程序初始化的东西,让我们称之为atinit().
初始化这些全局变量需要执行代码,编译器无法确定该值.因此,编译器会生成执行表达式并分配值的机器代码片段.这些片段需要在main()运行之前执行.
这就是atinit()发挥作用的地方.常见的CRT实现按顺序遍历atinit函数指针列表并执行初始化片段.问题是函数在atinit()列表中的注册顺序.虽然atexit()具有定义良好的LIFO顺序,并且它由代码调用atexit()的顺序隐式确定,但atinit函数不是这种情况.语言规范不需要订单,您可以在代码中执行任何操作来指定订单.SIOF就是结果.
一种可能的实现是编译器在单独的部分中发出函数指针.链接器合并它们,生成atinit列表.如果编译器执行此操作,则初始化顺序将由链接目标文件的顺序决定.查看映射文件,如果编译器执行此操作,您应该看到atinit部分.它不会被称为atinit,但可能会出现某种带有"init"的名称.看一下调用main()的CRT源代码也应该给出见解.