I was looking for the source for glibc's rand() function, which an answer here links to.
Following the link, I'm puzzled about the code for the __random_r() TYPE_0 branch:
int32_t val = state[0];
val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
state[0] = val;
*result = val;
What is the point of the val
variable, getting assigned and then immediately overwritten? The random_data
struct that holds state is nothing unusual.
As one would expect, compiling with -O2
on godbolt gives the same code if you just eliminate val
. Is there a known reason for this pattern?
UPDATE: This seems it was an aberration in the version linked to from that answer, I've updated the links there to the 2.28 version. It might have been something that was done temporarily to aid in debugging by making the contents of state[0]
easier to see in a local watchlist?
Wow, that is indeed some unbelievable garbage code.
There is no justification for this.
And not only is initialization of val
not needed, the fact is that state[0]
is an int32_t
, and multiplication by 1103515245
will trigger undefined behaviour in GCC (integer overflow) on any platform with 32-bit int
s (= basically every one). And GCC is the compiler most often used to compile Glibc.
As noted by HostileFork, the code in more recent 2.28 reads:
int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
state[0] = val;
*result = val;
With this, not only is the useless initialization removed, but the U
suffix makes the multiplication happen with unsigned integers, avoiding undefined behaviour. The & 0x7fffffff
ensures that the resulting value fits into an int32_t
and is positive.
User contributions licensed under CC BY-SA 3.0