为什么在不同的程序运行中,将变量设置为其自身地址会产生不同的结果?

6

昨天我遇到了这个实现康威生命游戏的混淆C代码:https://github.com/duckythescientist/obfuscatedLife/blob/master/life.c。作为一个伪随机生成器,它写的代码如下:

int pseudoRand = (int) &pseudoRand;

根据程序作者的评论

这是一个大的数字,应该在每次运行时都不同,因此作为种子很好用。

我相当肯定这里的行为要么是实现定义的,要么是未定义的。然而,我不确定为什么这个值会在每次运行时有所变化。我对大多数操作系统工作方式的理解是,由于虚拟内存的缘故,栈在每次程序运行时都被初始化为相同的虚拟地址,因此地址应该每次都相同。
这段代码是否会在大多数操作系统上产生不同的结果?它是否与操作系统有关?如果是这样,为什么操作系统会将同一程序映射到每次运行时的不同虚拟地址?
谢谢!

它只在某些操作系统架构上有所不同。最好的情况下,它是一个非常不可靠的种子。(但我想比采样时钟更加混淆。) - Hot Licks
1
大多数 IOCCC 获奖作品都包含一些未定义行为,这一点并不令人惊讶。 - n. m.
尽管我知道这可能是未定义行为(UB),但我的问题是为什么值每次会有所不同。这取决于编译器和操作系统实际执行的操作,而目前我并不理解。 - templatetypedef
5
没有地址空间布局随机化(ASLR),同一个二进制文件的每次运行很可能会得到相同的地址,特别是对于堆栈变量而言。 - Medinoc
1
你比我快了45秒... @Medinoc 至少这里有链接:http://en.wikipedia.org/wiki/Address_space_layout_randomization - alk
1个回答

3

虽然自动存储对象的分配地址是未指定的(将地址转换为整数也是实现定义的),但您在此情况下所做的只是窃取内核作为地址空间布局随机化(ASLR)的一部分分配给初始堆栈地址的熵。将其用作可能泄漏出程序的熵源是一个坏主意,特别是在与不受信任、可能有恶意的远程主机交互的应用程序中,因为您实际上正在向攻击者显示内核为您分配的随机地址基础,从而破坏了ASLR的目的。(即使您只是将其用作种子,只要攻击者知道PRNG算法,他们就可以反转它以获得种子。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接