malloc函数的返回值的随机性是多少?

时间:2016-11-04 18:20:02

标签: c random malloc

我在一个古老而尘土飞扬的项目中找到了这段代码:

int *p = (int*)malloc(sizeof(p));           // generate random number
free(p);                                    // free up space
int rand = p%3;                             // get random value in between 0-2

除了我们在C标准库中获得srand之外它是不好的样式和不必要的,返回值的实际随机性是多少?

虽然在使用它的上下文中不需要真正的随机性,但我每次测试它的次数为99999999次,并且每次测试运行rand == 0都比其他情况(rand == 1更少。和rand == 2)。

一个例子:

  • rand == 0:在99999999中有27343746次
  • rand == 1:99999999中的36328138次
  • rand == 2:在99999999中有36328115次

1 个答案:

答案 0 :(得分:2)

这是获取随机数的一种非常愚蠢的方式。它的行为非常依赖于平台以及应用程序代码正在做什么。例如,如果你在没有进行其他内存分配的循环中调用它,那么在许多系统上free将一遍又一遍地返回相同的块,因为p将它返回到免费的前面列表,所以每次rand==0都是一样的。在许多其他的情况下,当堆增长到一定大小时,最终会得到一个循环,然后分配器循环通过多个插槽。

这一特殊可能性显然在您的实验中发生了什么:您在70/256个案例中获得rand==1,在93/256个案例中获得rand==2p(除此之外,可能来自前几个尚未达到周期的分配和最后一个部分周期)。我不太熟悉malloc实现来解释这个特定的分布;可能malloc使用的控制结构的大小是3的倍数,这会产生模3的偏差。

模数为2的幂,你会在每个现实平台上产生偏差,因为保证任何类型的返回值都能正确对齐,并且大多数平台对2的幂都有对齐约束。或者换句话说, rand的最低位总是很少。

malloc是标准的C,并且在大多数平台上都很糟糕(甚至没有考虑将它用于与安全相关的任何事情,甚至对于概率算法来说它通常也不够好),它很少会比malloc输出更差。

可能有一些平台,其中{{1}}的返回值被随机化以利用缓冲区溢出和免费使用后的错误(因为攻击者无法预测有趣的对象在哪里)将与ASLR)一样,但这样的平台无论如何都会有更好的随机生成器API。