不同的函数有不同的地址吗? [英] Do distinct functions have distinct addresses?

查看:160
本文介绍了不同的函数有不同的地址吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这两个函数:

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

是保证& foo!=& bar



同样,

 模板< class T& void foo(){} 

是保证& foo< int> ; !=& foo< double>








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



Gold链接器还折叠函数,同时安全全部设置。 safe 表示如果采用函数地址,它不会折叠,而 all 。因此,如果函数具有不同的地址,那么黄金的折叠 safe 会表现为:



折叠可能是意外的,依赖于具有不同地址的不同(相同的实现)函数的代码(因此折叠可能是危险的),在当前C ++标准下它实际上是非法的吗? (C ++ 14 at this point)(当然,如果安全折叠合法)

解决方案

它看起来像是缺陷报告1400:函数指针平等处理这个问题,似乎在我说,这是可以做这个优化,但如评论表明,有不同意。它说(强调我):


根据5.10 [expr.eq]两个函数指针只有
如果它们指向相同的函数,则比较等于。但是,作为
优化,实现当前是别名函数
具有相同的定义。不清楚标准是否需要
来明确处理此优化。


,响应为:


标准清楚了需求,实现是
在as- ifrule


问题是询问两个问题:




  • 这些指针被认为是等价的

  • 是否可以合并函数



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


  1. 是确定,标准给出了在 as-if规则下的自由。 < em> as-if规则< / em>在 1.9 中有所描述,并且意味着实现仅需要模仿关于标准的要求的可观察行为。 这仍然是我对回应的解释。


  2. 这个问题完全被忽略,该标准是必需的,因为明确的 as-if规则涵盖了这一点,但是解释作为练习留给读者。虽然我承认由于回应的简洁,我不能否定这个观点,它最终是一个完全无益的反应。它也似乎与其他 NAD 问题中的响应不一致,就我可以告诉问题,如果他们存在。


草案标准的内容



因为我们知道我们正在处理

,我们可以从那里开始,注意 1.8 部分说:



< blockquote>

除非一个对象是一个位字段或一个基本类的子对象为零
大小,该对象的地址是它
占据的第一个字节的地址。不是位字段的两个对象可以具有相同的
地址,如果一个是另一个的子对象,或者如果至少一个是零大小的
基本类子对象,并且它们具有不同的类型;
否则,它们将有不同的地址。 4


并注意 4 说:


在as-if规则下,允许实现存储两个
对象在同一个机器地址或根本不存储对象如果
程序不能观察到差异


该部分的注释说:


函数不是一个对象,不管它是否占用
存储对象的方式


尽管它不是规范性的,但是在 1 在一个函数的上下文中没有意义,所以它与这个注释是一致的。因此,我们明确限制了对某些异常进行别名对象的限制,但不适用于函数。



接下来我们有 5.10 。]如果两个指针都为空,则两个指针比较相等,都指向
相同的函数,或者两者都表示相同的地址
(3.9.2),
否则它们比较不相等


它告诉我们两个指针是否相等:




  • 空指针

  • 指向相同的函数

  • 表示相同的地址



    • 或两者都表示相同的地址似乎给予足够的纬度,允许编译器对两个不同的函数进行别名,并且不需要指向不同函数的指针比较不等。



      观察结果



      Keith Thompson做了一些伟大的观察,因为他们涉及到核心问题,他补充说:


      如果程序打印了& foo ==& bar ,这是可观察的行为;所讨论的优化改变了可观察的行为。


      这是我同意的,如果我们可以表明有一个要求的指针是不相等的,确实违反 as-if规则,但到目前为止我们无法显示。



      和:


      [...]考虑一个定义空函数并使用
      地址作为唯一值的程序(考虑 SIG_DFL SIG_ERR SIG_IGN
      < signal.h> / < csignal> )。分配相同的地址
      打破这样的程序


      正如我在注释中指出的,C标准需要这些宏从C11中的 7.14 生成不同的值


      [...],它扩展为具有不同值的常量表达式,
      具有与第二个参数兼容的类型,以及信号函数的返回值
      ,并且其值与不等于
      任何可声明函数的地址[...]


      因此,尽管这种情况可能还有其他情况此优化很危险。



      更新



      JanHubičkaa gcc 开发人员撰写了一篇博文链接时间和过程间



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


      这不符合将两个函数转换为相同的地址,所以MSVC在这里是相当积极的。例如,这样做会打破GCC本身,因为我的惊喜地址比较是在预编译头文件中完成的。


      事后看来,经过几个月的阅读缺陷报告和思考优化问题后,偏向于更保守地反映委员会的反应。取一个函数的地址是可观察的行为,因此折叠相同的函数将违反 as-if规则


      Consider these two functions:

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

      is it guaranteed that &foo != &bar?

      Similarly,

      template<class T> void foo() { }
      

      is it guaranteed that &foo<int> != &foo<double>?


      There are two linkers I know of that fold function definitions together.

      MSVC aggressively COMDAT folds functions, so two functions with the same implementation can be turned into one function. As a side effect, the two functions share the same address. I was under the impression that this was illegal, but I cannot find where in the standard it is made illegal.

      The Gold linker also folds functions, with both a safe and all setting. safe means that if a function address is taken, it is not folded, while all folds even if the address is taken. So gold's fold safe behaves as-if functions have distinct addresses.

      While folding might be unexpected, and there is code that relies on distinct (identical implementation) functions having different addresses (so it can be dangerous to fold), is it actually illegal under the current C++ standard? (C++14 at this point) (Naturally as-if safe folding is legal)

      解决方案

      It looks like defect report 1400: Function pointer equality deals with this issue and seems to me to say that it is okay to do this optimization but as comments indicate, there is disagreement. It says (emphasis mine):

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

      and the response was:

      The Standard is clear on the requirements, and implementations are free to optimize within the constraints of the "as-if" rule.

      The question is asking about two issues:

      • Is it okay for these pointers to be considered equal
      • Is it okay to coalesce the functions

      Based on comments I see two interpretations of the response:

      1. This optimization is ok, the standard gives the implementation this freedom under the as-if rule. The as-if rule is covered in section 1.9 and means the implementation only has to emulate the observable behavior with respect to the requirements of the standard. This is still my interpretation of the response.

      2. The issue is at hand is completely ignored and the statement merely says no adjustment to the standard is required because clearly the as-if rules covers this but the interpretation is left as an exercise to the reader. Although I acknowledge due to the terseness of the response I can not dismiss this view, it ends up being a totally unhelpful response. It also seems inconsistent with the responses in the other NAD issues which as far as I can tell point out issue if they exist.

      What the draft standard says

      Since we know we are dealing with the as-if rule, we can start there and note that section 1.8 says:

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

      and note 4 says:

      Under the "as-if" rule an implementation is allowed to store two objects at the same machine address or not store an object at all if the program cannot observe the difference

      but a note from that section says:

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

      although it is not normative, the requirements for an object laid out in paragraph 1 do not make sense in the context of a function and so it is consistent with this note. So we are explicitly restricted from aliasing objects with some exceptions but not such restriction applies to functions.

      Next we have section 5.10 Equality operators which says (emphasis mine):

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

      which tells us two pointers are equal if they are:

      • Null pointers
      • Point to the same function
      • Represent the same address

      The or both represent the same address seems to give enough latitude to allow a compiler to alias two different functions and does not require pointers to different functions to compare unequal.

      Observations

      Keith Thompson has made some great observations that I feel are worth adding to the answer since they get to core issues involved, he says:

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

      which I agree with and if we could shows that there is a requirement for the pointers to be unequal that would indeed violate the as-if rule but so far we can not show that.

      and:

      [...]consider a program that defines empty function and uses their addresses as unique values (think about SIG_DFL, SIG_ERR, and SIG_IGN in <signal.h> / <csignal>). Assigning them the same address would break such a program

      As I noted in my comment the C standard requires these macros to generate distinct values, from 7.14 in C11:

      [...]which expand to constant expressions with distinct values that have type compatible with the second argument to, and the return value of, the signal function, and whose values compare unequal to the address of any declarable function[...]

      So although this case is covered perhaps there are other cases that would make this optimization dangerous.

      Update

      Jan Hubička a gcc developer wrote a blog post Link time and inter-procedural optimization improvements in GCC 5, code folding was one of many topics he covered.

      I asked him to comment on whether folding identical functions to the same address was conforming behavior or not and he says it is not conforming behavior and indeed such an optimization would break gcc itself:

      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.

      In hindsight, after months more of reading defect reports and thinking about optimization issues, I am biased towards a more conservative reading of the committee's response. Taking the address of a function is observable behavior and therefore folding identical functions would violate the as-if rule.

      这篇关于不同的函数有不同的地址吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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