为了调试的目的,我想 malloc
每次执行程序时都返回相同的地址,但在MSVC中却不是这样的。
#include <stdlib.h>
#include <stdio.h>
int main() {
int test = 5;
printf("Stack: %p\n", &test);
printf("Heap: %p\n", malloc(4));
return 0;
}
用cygwin的gcc编译,每次都得到相同的Stack地址和Heap地址,而用msvc编译时aslr关闭... ...
cl t.c /link /DYNAMICBASE:NO /NXCOMPAT:NO
...我每次都得到相同的堆栈地址,但堆栈地址会改变。
我已经试过在注册表中加入 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\MoveImages
但却无法工作。
返回的栈地址和指针都是由 malloc()
可能每次都不同。事实上,当程序被编译并在MacOS上多次运行时,两者都有所不同。
编译器或操作系统可能会导致这种行为,以尝试并使其更难以利用软件缺陷。在某些情况下,可能有一种方法可以防止这种情况,但如果你的目标是重播相同的一系列的 malloc()
地址,其他因素可能会改变地址,例如时间敏感行为、文件系统的副作用,更不用说非决定性的线程行为。你应该尽量避免依赖这个来进行测试。
还需要注意的是 &test
当作 (void *)
作为 %p
期待 void
指针,它不能保证与 int *
.
事实证明,你可能无法从MSVC运行时库中获得确定性行为。 无论是调试版还是生产版的CC++运行库,最终都会调用一个名为------的函数。 _malloc_base()
,进而调用Win32 API函数 HeapAlloc(). 遗憾的是,这两种情况都没有发生。HeapAlloc()
也不是提供其堆的函数。HeapCreate(),记录一个标志或其他方式来获得确定性行为。
你可以在你自己的分配方案的基础上,在 VirtualAlloc()
如同@Enosh_Cohen所建议的那样,但这样一来,你就会松开了 调试功能 MSVC分配函数提供的。
堆的性质是这样的,它给你下一个可用的段,它可能位于任何地方。理论上,堆可以通过malloc完成的底层API调用与计算机上的其他一切共享。
此外,托管的操作系统利用 地址空间布局随机化 (ASLR)来防止漏洞。意味着无论是堆栈还是堆地址都不能保证在执行之间保持不变。