当前位置: 首页 > 知识库问答 >
问题:

从函数返回struct时可能存在GCC错误

冯庆
2023-03-14

我相信我在执行O'Neill的PCG PRNG时在GCC中发现了一个bug。(Godbolt的编译器资源管理器上的初始代码)

#include <stdint.h>

struct retstruct {
    uint32_t a;
    uint64_t b;
};

struct retstruct fn(uint64_t input)
{
    struct retstruct ret;

    ret.a = 0;
    ret.b = input * 11111111111 + 111111111111;

    return ret;
}

生成的程序集(GCC 9.2,x86_64,-O3):

fn:
  movabs rdx, 11111111111     # multiplier constant (doesn't fit in imm32)
  xor eax, eax                # ret.a = 0
  imul rdi, rdx
  movabs rdx, 111111111111    # add constant; one more 1 than multiplier
     # missing   add rdx, rdi   # ret.b=... that we get with clang or older gcc
  ret
# returns RDX:RAX = constant 111111111111 : 0
# independent of input RDI, and not using the imul result it just computed

有趣的是,修改结构以使uint64_t作为第一个成员产生正确的代码,就像将两个成员都更改为uint64_t一样

x86-64 System V在rdx:rax中返回小于16字节的结构,但它们是可以复制的。在本例中,第二个成员是RDX,因为RAX的高半部分是用于对齐或.b的填充,而.a是较窄的类型。(sizeof(retstruct)无论哪种方式都是16;我们没有使用__attribute__((packed)),因此它尊重alignof(uint64_t)=8。)

如果没有,应该在https://gcc.gnu.org/bugzilla/上报告这一点

共有1个答案

皇甫喜
2023-03-14

我在这里没有看到任何UB;您的类型是未签名的,所以签名溢出UB是不可能的,没有什么奇怪的。(即使签名,它也必须为不会导致溢出UB的输入产生正确的输出,如rdi=1)。它也被GCC的C++前端打破了。

此外,GCC8.2为AArch64和RISC-V正确编译了它(在使用movk构造常数之后,将其编译为madd指令,或者在加载常数之后,将其编译为RISC-V mul和add指令)。如果GCC找到的是UB,我们通常希望它找到UB,并为其他ISA破译代码,至少是具有类似类型宽度和寄存器宽度的ISA破译代码。

Clang也会正确地编译它。

您可以使用问题中的MCVE在GCC的bugzilla上报告这一点。

这看起来确实是x86-64 System V结构返回处理中的一个bug,可能是包含填充的结构。这就解释了为什么它在内联和将A扩展为uint64_t(避免填充)时起作用。

 类似资料:
  • 我正在等待(从USSD请求中)检索一个值,以便返回它(getUSSD):

  • 我正在用Python作为后端编写一个应用程序,当我试图返回一个函数的变量时,我得到以下错误 这是我使用的代码 有人知道这个问题的答案吗?

  • 问题内容: 这是输出: 为什么JSON本质上是空的? 问题答案: 您需要通过大写字段名称中的第一个字母来导出 TestObject中的字段。更改为,依此类推。 encoding / json包和类似的包会忽略未导出的字段。 字段声明之后的字符串是struct标签。在与JSON封送时,此struct中的标记设置该结构的字段名称。

  • 我接受了一次采访,被问到一个问题,我想了解解决方案。 创建一个递归函数,该函数返回给定长度的数组的可能组合数,这些数组可以由非重复连续整数数组组成。 f(数组,长度)=组合 数组=[0,1,2,3] 长度=2 组合=10(所有组合:[0,0][0,1][0,2][0,3][1,1][1,2][1,3][2,2][2,3][3,3]) 请注意,允许使用[0,0],但不允许使用[1,0],因为定义了[

  • 我正在使用Tensorflow和Flask开发一个python(3.6)项目。我需要在flask函数中运行Tensorflow模型,但它返回一个错误。 这是我的密码: 应用程序。派克 但当我运行我的flask应用程序时,它返回错误为: 2018-09-05 11:08:54.952 Python[3772:69116]警告:NSWindow拖动区域只能在主线程上无效!这将在中引发异常 未来。从(0

  • 我得到了这个错误,我知道这个问题已经在这里解决过了,因为人们没有在函数中添加返回->。我不明白为什么这仍然给我带来错误。