【发布时间】:2009-01-10 02:14:59
【问题描述】:
任何人都可以链接到 C++ 标准关于编译器删除全局和静态符号的内容?我以为您不能保证如果未引用全局符号,编译器将删除它们。我的一位同事断言,如果您的全局符号包含在主翻译单元中,即使没有引用这些符号,也不会被删除。
【问题讨论】:
标签: c++ compiler-construction linker
任何人都可以链接到 C++ 标准关于编译器删除全局和静态符号的内容?我以为您不能保证如果未引用全局符号,编译器将删除它们。我的一位同事断言,如果您的全局符号包含在主翻译单元中,即使没有引用这些符号,也不会被删除。
【问题讨论】:
标签: c++ compiler-construction linker
有趣的是,在 C++2003 标准中我能找到的只有这个:
3.7.1 静态存储时长 [basic.stc.static]
所有没有动态的对象 存储期限也没有本地有 静态存储时间。存储 对于这些对象应持续 计划的持续时间(3.6.2, 3.6.3)。
如果是静态存储的对象 持续时间有初始化或 具有副作用的析构函数,它应该 即使出现也不会被淘汰 未被使用,除了一个类 对象或其副本可能会被消除 如指定 12.8.
这意味着该标准允许在静态存储中删除项目,如果它们的初始化和销毁没有副作用并且它们在其他情况下未被使用。
如果有更直接的许可,我没有看到(但也许其他人会看到)。
但是,应该注意的是,让链接器消除最终图像中未使用的对象是一种非常常见的优化。
【讨论】:
您问的是关于链接的问题,尽管 C++ 标准规定链接应该作为翻译的最后阶段进行,但它没有说明应该如何进行。例如,它说函数引用被解析,但它不要求它们按名称解析,也没有说明解析后引用会发生什么。
要确定编译器在目标代码中包含哪些符号,以及链接器删除或不删除哪些符号,您需要分别查阅您正在使用的编译器和链接器的文档。
【讨论】:
我相信就是这样(我们之前在评论线程中就堆栈溢出问题进行了长时间的讨论):
在任何情况下,编译器都必须在使用完成之前初始化对象,但不一定在 main 之前。我做了测试,因为 stackoverflow 的某个人说如果没有这样的用途,gcc 会有效地优化具有副作用的对象的初始化。我现在测试了,我已经看到 gcc 没有这样做。此外,据我了解标准,无论如何都不允许这样做。
如果你只取一个对象的地址或你想要初始化的对象的翻译单元的函数就足够了。为了安全起见,最好始终这样做,即使对于具有副作用的初始化对象也是如此。假设您的朋友是对的,我认为对于 main 的翻译单元,main 始终被视为被使用,因此该条件立即得到满足。规则可以在3.6.2p3、3.7.1p2和3.2p2(使用的定义)、1.9p7(副作用的定义)中找到。
【讨论】: