为什么 glibc 的 __random_r 分配它立即覆盖的变量?
Why is glibc's __random_r assigning variables it immediately overwrites?
我正在寻找 glibc 的 rand() 函数的源代码,an answer here links to。
在 link 之后,我对 __random_r() TYPE_0 branch 的代码感到困惑:
int32_t val = state[0];
val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
state[0] = val;
*result = val;
val
变量被赋值后立即被覆盖的意义何在?保存状态的 random_data
结构是 nothing unusual.
正如人们所期望的那样,如果您只是删除 val
,则在 godbolt 上使用 -O2
进行编译会得到相同的代码。这种模式有已知的原因吗?
更新: 这似乎是 link 从那个答案 I've updated the links there to the 2.28 version 编辑的版本中的一个偏差。这可能是为了通过使 state[0]
的内容更容易在本地监视列表中查看来帮助调试而临时完成的?
哇,这确实是一些令人难以置信的垃圾代码。
没有理由这样做。
不仅不需要 val
的初始化,事实上 state[0]
是一个 int32_t
,乘以 1103515245
将 在任何具有 32 位 int
s(= 基本上每个)的平台上触发 GCC 中的未定义行为(整数溢出)。而GCC是最常用于编译Glibc的编译器。
如 所述,最近的 2.28 中的代码如下:
int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
state[0] = val;
*result = val;
有了这个,不仅删除了无用的初始化,而且 U
后缀使乘法与无符号整数一起发生,避免了未定义的行为。 & 0x7fffffff
确保结果值适合 int32_t
并且是正数。
我正在寻找 glibc 的 rand() 函数的源代码,an answer here links to。
在 link 之后,我对 __random_r() TYPE_0 branch 的代码感到困惑:
int32_t val = state[0];
val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
state[0] = val;
*result = val;
val
变量被赋值后立即被覆盖的意义何在?保存状态的 random_data
结构是 nothing unusual.
正如人们所期望的那样,如果您只是删除 val
,则在 godbolt 上使用 -O2
进行编译会得到相同的代码。这种模式有已知的原因吗?
更新: 这似乎是 link 从那个答案 I've updated the links there to the 2.28 version 编辑的版本中的一个偏差。这可能是为了通过使 state[0]
的内容更容易在本地监视列表中查看来帮助调试而临时完成的?
哇,这确实是一些令人难以置信的垃圾代码。
没有理由这样做。
不仅不需要 val
的初始化,事实上 state[0]
是一个 int32_t
,乘以 1103515245
将 在任何具有 32 位 int
s(= 基本上每个)的平台上触发 GCC 中的未定义行为(整数溢出)。而GCC是最常用于编译Glibc的编译器。
如
int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
state[0] = val;
*result = val;
有了这个,不仅删除了无用的初始化,而且 U
后缀使乘法与无符号整数一起发生,避免了未定义的行为。 & 0x7fffffff
确保结果值适合 int32_t
并且是正数。