链接器为什么不能阻止C ++静态初始化顺序的失败? [英] Why can't the linker prevent the C++ static initialization order fiasco?

查看:70
本文介绍了链接器为什么不能阻止C ++静态初始化顺序的失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:将下面的示例更改为实际演示SIOF的示例.

Changed example below to one that actually demonstrates the SIOF.

我试图理解此问题的所有细微之处,因为在我看来,这似乎是该语言中的一个主要漏洞.我已经知道链接器无法阻止它,但是为什么会这样呢?在像这样的简单情况下进行预防似乎很简单:

I am trying to understand all of the subtleties of this problem, because it seems to me to be a major hole in the language. I have read that it cannot be prevented by the linker, but why is this so? It seems trivial to prevent in simple cases, like this:

// A.h
extern int x;

// A.cpp
#include <cstdlib>

int x = rand();

// B.cpp
#include "A.h"
#include <iostream>

int y = x;

int main()
{
    std::cout << y; // prints the random value (or garbage)?
}

在这里,链接器应该能够轻松地确定A.cpp的初始化代码应该在链接的可执行文件中的B.cpp之前发生,因为B.cpp依赖于A.cpp中定义的符号(而且链接器显然是已经必须解决此引用).

Here, the linker should be able to easily determine that the initialization code for A.cpp should happen before B.cpp in the linked executable, because B.cpp depends on a symbol defined in A.cpp (and the linker obviously already has to resolve this reference).

所以为什么不能将其推广到所有编译单元.如果链接器检测到循环依赖关系,它是否会因为错误而使链接失败(或者可能是警告,因为这可能是程序员的意图,我想在一个编译单元中定义一个全局符号,然后在另一个编译单元中对其进行初始化) ?

So why can't this be generalized to all compilation units. If the linker detects a circular dependency, can't it just fail the link with an error (or perhaps a warning, since it may be the programmer's intent I suppose to define a global symbol in one compilation unit, and initialize it in another)?

在简单情况下,标准是否对实现征收任何要求以确保正确的初始化顺序?不可能做到这一点的例子是什么?

Does the standard levy any requirements on an implementation to ensure the proper initialization order in simple cases? What is an example of a case where this would not be possible?

我知道类似的情况可能在全球销毁时发生.如果程序员没有仔细确保破坏过程中的依赖关系与构造对称,则会发生类似的问题.链接程序也不会对这种情况发出警告吗?

I understand that an analogous situation can occur at global destruction time. If the programmer does not carefully ensure that the dependencies during destruction are symmetrical to construction, a similar problem occurs. Could the linker not warn about this scenario as well?

推荐答案

链接器通常只是链接-即它们解析地址.您似乎希望他们对代码进行语义分析.但是他们无权访问语义信息-只有一堆目标代码.现代的链接器至少可以处理较大的符号名称,并丢弃重复的符号以使模板更有用,但是只要链接器和编译器是独立的,就可以了.当然,如果链接程序和编译器都是由同一个团队开发的,并且如果该团队是一个大公司,则可以在链接程序中添加更多的信息,但是很难看到可移植语言的标准如何强制执行此类操作.

Linkers traditionally just link - i.e. they resolve addresses. You seem to be wanting them to do semantic analysis of the code. But they don't have access to semantic information - only a bunch of object code. Modern linkers at least can handle large symbol names and discard duplicate symbols to make templates more useable, but so long as linkers and compilers are independent, that's about it. Of course if both linker and compiler are developed by the same team, and if that team is a big corporation, more intelligence can be put in the linker, but it's hard to see how a standard for a portable language can mandate such a thing.

如果您想了解有关链接器BTW的更多信息,请查看 http://www.iecc. com/linker/-关于经常被忽略的工具的唯一书籍.

If you want to know more about linkers, BTW, take a look at http://www.iecc.com/linker/ - about the only book on an often ignored tool.

这篇关于链接器为什么不能阻止C ++静态初始化顺序的失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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