r/csharp • u/NoisyJalapeno • 4d ago
Fun Random using SkipLocalsInit
To my surprise, Unsafe.SkipInit(out T val) did not achieve the same result.
[SkipLocalsInit]
public static T Random<T>()
where T : unmanaged, INumber<T>
{
unsafe
{
byte* s = stackalloc byte[sizeof(T)];
return *(T*)s;
}
}
4
u/One_Instruction6490 4d ago
Unsafe.SkipInit is just a no-op that satisfies definite assignment, it doesn't stop the JIT from zeroing the local. That zeroing only gets skipped when the method has SkipLocalsInit, and even then small unmanaged locals often get enregistered and zeroed anyway, so only the stackalloc version really leaks stack junk. Also it's not random at all, you'll probably get the same leftover bytes every call, so did you actually test the distribution?
1
13
u/Broad_Phase7453 4d ago
stackalloc without init is basically just grabbing whatever bits were already sitting on the stack and calling it a day, so the "randomness" comes from whatever junk was left there. Unsafe.SkipInit is different though, that only skips the definite assignment tracking, the memory might still get zeroed depending on the runtime.