为什么 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 位 ints(= 基本上每个)的平台上触发 GCC 中的未定义行为(整数溢出)。而GCC是最常用于编译Glibc的编译器。


所述,最近的 2.28 中的代码如下:

int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
state[0] = val;
*result = val;

有了这个,不仅删除了无用的初始化,而且 U 后缀使乘法与无符号整数一起发生,避免了未定义的行为。 & 0x7fffffff 确保结果值适合 int32_t 并且是正数。