gpt4 book ai didi

c++ - 不同的函数有不同的地址吗?

转载 作者:IT老高 更新时间:2023-10-28 13:59:30 25 4
gpt4 key购买 nike

考虑这两个函数:

void foo() {}
void bar() {}

是否保证&foo != &bar ?

同样,

template<class T> void foo() { }

是否保证&foo<int> != &foo<double> ?


我知道有两个链接器将函数定义放在一起。

MSVC 积极地 COMDAT 折叠函数,因此具有相同实现的两个函数可以变成一个函数。作为副作用,这两个函数共享相同的地址。我的印象是这是非法的,但我在标准中找不到它是非法的。

The Gold linker也可以折叠函数,同时具有 safeall环境。 safe表示如果取一个函数地址,则不折叠,而all即使地址被占用,也会折叠。所以黄金的折叠safe表现得好像函数具有不同的地址。

虽然折叠可能出乎意料,并且有些代码依赖于具有不同地址的不同(相同实现)函数(因此折叠可能很危险),但在当前 C++ 标准下它实际上是非法的吗? (此时为 C++14)(自然好像 safe 折叠是合法的)

最佳答案

看起来像 defect report 1400: Function pointer equality处理这个问题,在我看来,可以进行此优化,但正如评论所示,存在分歧。它说(强调我的):

According to 5.10 [expr.eq] paragraph 2, two function pointers onlycompare equal if they point to the same function. However, as anoptimization, implementations are currently aliasing functions thathave identical definitions. It is not clear whether the Standard needsto deal explicitly with this optimization or not.

得到的回应是:

The Standard is clear on the requirements, and implementations arefree to optimize within the constraints of the “as-if” rule.

问题是问两个问题:

  • 是否可以将这些指针视为相等
  • 可以合并函数吗

根据评论,我看到了对响应的两种解释:

  1. 这个优化没问题,标准在as-if规则下给了实现这个自由。 as-if 规则 包含在 1.9 部分中,这意味着实现只需模拟符合标准要求的可观察行为。 这仍然是我对响应的解释。

  2. 手头的问题完全被忽略了,声明只是说不需要对标准进行调整,因为显然 as-if 规则 涵盖了这一点,但解释留作练习给读者。尽管我承认由于回答的简洁,我不能否认这种观点,但它最终是一个完全没有帮助的回答。它似乎也与其他 NAD 问题中的响应不一致,据我所知,如果它们存在,请指出问题。

标准草案的内容

既然我们知道我们正在处理 as-if 规则,我们可以从那里开始并注意 1.8 部分说:

Unless an object is a bit-field or a base class subobject of zerosize, the address of that object is the address of the first byte itoccupies. Two objects that are not bit-fields may have the sameaddress if one is a subobject of the other, or if at least one is abase class subobject of zero size and they are of different types;otherwise, they shall have distinct addresses.4

并注意 4 说:

Under the “as-if” rule an implementation is allowed to store twoobjects at the same machine address or not store an object at all ifthe program cannot observe the difference

但该部分的注释说:

A function is not an object, regardless of whether or not it occupiesstorage in the way that objects do

虽然它不是规范性的,但在第 1 段中列出的对象要求在函数的上下文中没有意义,因此与本注释一致。因此,我们明确限制为对象使用别名,但有一些异常(exception),但这种限制不适用于函数。

接下来我们有部分 5.10 平等运算符 说(强调我的):

[...]Two pointers compare equal if they are both null, both point tothe same function, or both represent the same address (3.9.2),otherwise they compare unequal.

告诉我们两个指针如果相等则相等:

  • 空指针
  • 指向同一个函数
  • 代表同一个地址

或两者都代表相同的地址似乎提供了足够的自由度以允许编译器为两个不同的函数起别名,并且不需要指向不同函数的指针来比较不相等。

观察

基思·汤普森(Keith Thompson)提出了一些很好的意见,我认为这些意见值得添加到答案中,因为它们涉及到所涉及的核心问题,他说:

If a program prints the result of &foo == &bar, that's observable behavior; the optimization in question changes the observable behavior.

我同意这一点,如果我们能证明指针不相等的要求确实违反了 as-if 规则,但到目前为止我们还不能证明这一点。

和:

[...]consider a program that defines empty function and uses theiraddresses as unique values (think about SIG_DFL, SIG_ERR, and SIG_IGNin <signal.h> / <csignal>). Assigning them the same address wouldbreak such a program

正如我在评论中指出的,C 标准要求这些宏从 C11 中的 7.14 生成不同的值:

[...]which expand to constant expressions with distinct values thathave type compatible with the second argument to, and the return valueof, the signal function, and whose values compare unequal to theaddress of any declarable function[...]

因此,尽管已经涵盖了这种情况,但可能还有其他情况会使这种优化变得危险。

更新

gcc 开发人员 Jan Hubička 写了一篇博文 Link time and inter-procedural optimization improvements in GCC 5 ,代码折叠是他涵盖的众多主题之一。

我请他评论将相同的函数折叠到同一个地址是否符合行为,他说这不是符合行为,而且确实这样的优化会破坏 gcc 本身:

It is not conforming to turn two functions to have same address, so MSVC is quite aggressive here. Doing so, for example, breaks GCC itself because to my surprise address compare is done in the precompiled headers code. It works for many other projects, including Firefox.

事后看来,在阅读了几个月的缺陷报告和思考优化问题之后,我倾向于对委员会的回应进行更保守的解读。获取函数的地址是可观察到的行为,因此折叠相同的函数将违反 as-if 规则

更新 2

另见 llvm-dev discussion: Zero length function pointer equality :

This is a well-known conformance-violating bug in link.exe; LLVM should notbe making things worse by introducing a similar bug itself. Smarter linkers(for example, I think both lld and gold) will do identical functioncombining only if all but one of the function symbols is only used as thetarget of calls (and not to actually observe the address). And yes, thisnon-conforming behavior (rarely) breaks things in practice. See thisresearch paper.

关于c++ - 不同的函数有不同的地址吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26533740/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com