我可以使用 main 中 argc 的地址作为随机源吗?

Can I use the address of argc in main as random source?

我想创建一个只需要一个随机数的程序,所以我尝试使用main函数中argc的地址作为随机源,因为我认为程序在内存中的位置是随机的,而且它可以保存一些包含语句,所以我尝试了:

#include <stdio.h>
int main(int argc,const char* argv[]){
    printf("%lu\n",(unsigned long int)&argv/sizeof(unsigned long int));
    return 0;
}

但是我发现每次的输出都不是很"random":它们是4的倍数:

17591828907268
17591841542404
17591845040388
17591834556676

这是什么原因?是否可以使用 argc 的地址作为随机数?

然后我尝试删除地址的一些位:

#include <stdio.h>
int main(int argc,const char* argv[]){
    printf("%lu\n",(unsigned long int)&argv >> 12);
    return 0;
}

这次看起来还蛮随意的,至少是单双数都有:

34359070631
34359034616
34359078055
34359080624

是"correct"把argc的地址变成随机数的方法吗?

What is the reason?

Alignment requirements 对于您的体系结构,我假设它是 x86 而 int 是 4 个字节,这意味着每个 int 应该与一个可以被 4 整除的地址对齐(正是您所看到的行为)。

And is using address of argc as random number possible?

可能吗? Yeah, sure。你就去做吧。

这是个好主意吗?不,绝对不是。原因见下文。

Is that "correct" way to turn the address of argc into random number?

我假设 "correct" 你的意思是熵的良好来源,答案是否定的。

现代操作系统中存在某种程度的 address space layout randomization,但这并不意味着是熵的良好来源。这只是为了让某人更难将您程序中的错误用作安全漏洞。而且确实没有关于 ASLR 的任何保证(如果你真的想要,你可以在某些操作系统中将其关闭)。

简而言之,您不应该使用变量的地址作为熵的来源。它只是不是随机性的良好来源。

它是 4 的倍数,因为函数地址在我所知道的每个平台上都是 word-aligned(我假设这是 x86 或 x86_64?)

argc 的地址在某种意义上可能是 "random",因为您可能不知道它是什么,所以如果您使用它来为游戏的起始条件设定种子或任何可能有用的东西;如果你将它用于加密或任何东西,绝对不要依赖它——攻击者可以做一些事情来影响 argc 的加载位置。

就是说,您的 C 库附带了完美可用的 rand() 和 srand() 函数,作为奖励,您可以故意为它添加一个特定的值,这对调试非常有帮助;每当我需要随机数时,我个人都会坚持这样做。

如果你真的需要随机性,你应该使用以下之一:

  1. /dev/random
  2. /dev/urandom

    有关这两个的信息,请参阅 How to use /dev/random or urandom in C?

  3. srand()

    关于播种 srand() 的信息在这里:Recommended way to initialize srand?

  4. 专门为其设计的外部库。

    这里有一些信息A good random number generator for C