我正在寻找glibc的rand()函数的源代码,其中
an answer here links to.
在链接之后,我对__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进行编译会得到相同的代码.这种模式有一个众所周知的原因吗?
更新:这似乎是与该答案相关联的版本中的一个异常,I’ve updated the links there to the 2.28 version.可能是暂时通过使状态[0]的内容更容易在本地监视列表中看到来帮助调试的东西?
最佳答案 哇,这确实是一些难以置信的垃圾代码.
没有理由这样做.
并且不仅需要val的初始化,事实是state [0]是一个int32_t,乘以1103515245将在任何具有32位整数的平台上触发GCC(整数溢出)中的未定义行为(=基本上每一个) . GCC是最常用于编译Glibc的编译器.
如HostileFork所述,最近的2.28中的代码为:
int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
state[0] = val;
*result = val;
这样,不仅删除了无用的初始化,而且U后缀使得无符号整数发生乘法,从而避免了未定义的行为. & 0x7fffffff确保结果值适合int32_t并且为正.