【问题标题】:What does uintptr_t have to do with strict aliasing?uintptr_t 与严格别名有什么关系?
【发布时间】:2020-11-18 15:39:55
【问题描述】:

我正在研究严格别名以及如何处理它,并在 DPDK 上找到了this commit。

为了修复严格的别名(根据 cmets),他们将 void* 参数 src 和 dst 转换为 uintptr_t。然后使用铸造版本。

据我了解,这与严格的别名规则无关,因为在规则本身中没有提到转换为 uintptr_t。

投到uintptr_t 真的有助于严格混叠吗?或者这只是解决来自 GCC 的一些可能的警告?

【问题讨论】:

  • 那个提交对我来说看起来像是假的,编译器不允许假设 void * 参数无论如何都没有别名 afaik,我不认为 const 改变任何东西。

标签: c strict-aliasing dpdk


【解决方案1】:

强制转换为 uintptr_t 真的有助于严格混叠吗?

不,不会的。

或者这只是修复来自 GCC 的一些可能的警告?

“修复”是为了很好地掩饰严格混叠违规行为,以至于编译器无法诊断它们,是的,它可能会。并且大概它确实对做出这种改变的人这样做了。

这是有害的,因为现在,编译器不仅可能对代码做一些不需要的事情,而且你甚至无法通过传递 -fno-strict-aliasing 选项(或其他编译器可能提供的任何类似选项)来阻止它这样做.更糟糕的是,它可能适用于今天使用的编译器,但在您升级到新版本或切换到不同的 C 实现时会中断数月或数年。

【讨论】:

  • 标准故意避免要求所有实现都适合低级编程。因此,真正努力使实现适用于此类目的的编译器编写者将需要使用他们自己的判断而不是标准来平衡优化与低支持级别的语义。整数到指针转换之类的东西经常出现在需要低级语义的代码中,这些语义会被“优化”的尝试破坏,很少出现,因此应该与任何寻求支持低级编程的编译器一起使用。
  • 我不反对,@supercat。当然,C 不要求编译器执行任何特定类别的优化或使用任何特定信息来指导他们执行的任何优化。但是是否存在严格别名违规是代码的功能,而不是编译器的功能。插入到整数和返回的转换不会改变通过指向特定数据类型的指针访问特定对象是否构成严格别名违规,无论是否有任何真正理由期望它会无论如何都按预期工作。
  • 严格别名规则的全部目的是指定编译器何时必须适应即使看起来简单的代码实际上也可能在做一些“棘手”的可能性。它从来没有打算让编译器忽略那些看起来很棘手的代码可能会做一些棘手的事情的可能性。没有“看起来很棘手”的定义,但是代码所做的事情越是棘手,高质量的编译器就越不可能错过所有这些。
  • @supercat,我没有参与起草标准的任何部分,但在我看来,严格别名规则的意图一直是完全允许编译器假设程序不会尝试执行某些棘手的事情。编译器不需要 SAR 来指示他们需要适应允许程序执行的操作,而不管 SAR。
  • SAR 仅旨在允许客户执行优化他们的特定客户会觉得有用,而不必适应极端情况对他们的客户来说并不重要。由于不同的客户有不同的需求,委员会期望编译器编写者比委员会更容易认识到哪些极端情况对他们的特定客户很重要。一般来说,是否应该定义某个动作 X 的决定不是基于“大多数程序员会发现 X 有用吗”这个问题,而是...
【解决方案2】:

“严格的别名规则”规定了即使是不适合低级编程的实现也必须允许看似不相关的对象之间出现别名的可能性。被设计为适合低级编程的编译器被允许并且将通过有意义的行为来扩展语言 - 通常在比标准要求的更多情况下“以环境的文档化方式”处理构造,特别是在存在通常无用的构造的情况下。

相对较少的不打算以低级方式访问存储的程序会执行整数到指针的转换。因此,将此类转换视为指示它们应该避免对由此形成的指针做出任何假设的实现将能够有效地处理比不这样做的程序更广泛的程序,而不必放弃许多真正的机会 -有用的优化。虽然最好让标准指定一种语法以擦除任何指针来源的证据,但通过整数类型的转换目前适用于除 clang 之外的几乎所有编译器。

【讨论】:

    猜你喜欢
    • 2020-08-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 2011-08-25
    • 2023-03-20
    • 2014-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多