我打错了吗?
#include <stdio.h>
#include <stdlib.h>
int
main( void )
{
int * p = malloc(100000);
int * q;
printf("%p\n%p\n", (void *)p, (void *)q);
(void)getchar(); /* to run several instances at same time */
free(p);
return 0;
}
无论是顺序运行还是同时运行多个终端,它总是为p
打印“0x60aa00000800”(q
不同)。
编辑:感谢您的回答,我感到困惑的一个原因是因为每次都使用打印不同的地址。事实证明,我开始使用的新编译器选项-fsanitize=address
导致了这种变化。糟糕。
答案 0 :(得分:6)
q
的值是未初始化的垃圾,因为您从未为其分配值。
每次运行程序时,p
获得相同的地址就不足为奇了。该地址几乎肯定是虚拟地址,因此它仅适用于当前正在运行的程序(进程)的内存空间。
从一个程序看到的虚拟地址0x60aa00000800
和从另一个程序看到的虚拟地址0x60aa00000800
是不同的物理地址。操作系统将虚拟地址映射到物理地址,反之亦然,因此没有冲突。 (如果不同的程序可以读取和写入相同的物理内存,那将是一场安全噩梦。)
如果它们每次都不同,也就不足为奇了。例如,某些操作系统随机化堆栈地址以防止某些代码漏洞。我不确定堆地址是否也是随机的,但它们当然可以。
答案 1 :(得分:3)
这种行为并不奇怪。 malloc
操作只是在进程中返回指向用户可寻址+已分配内存的指针。对于相同大小的第一个内存请求,通过进程的不同调用返回相同的地址是完全合理的
q
的行为与此并不矛盾。你给了q
没有值,因此它得到写入堆栈部分的最后一个值。毫不奇怪,未定义的行为会因同一进程的不同调用而有所不同(毕竟,它是未定义的)
答案 2 :(得分:2)
你的代码很好。
每次运行相同的代码,以及使用malloc()获取内存的相同算法,因此地址不应该是不同的。
q
的物理内存地址不同,但操作系统为每个进程提供内存虚拟视图,将不同的物理内存地址映射到进程中的相同虚拟地址。所以所有进程都有类似的内存视图(并且看不到其他进程的内存)答案 3 :(得分:1)
每次运行程序时,堆分配器都不需要提供不同/唯一的地址。无论如何都不能保证这一点,但是malloc()
的实现具有确定性行为并且每次运行程序时都给出相同的指针是完全合理的。
最后请注意,程序中的所有指针都是虚拟内存地址,而不是物理地址。因此,即使两个并发进程在指针中可能具有相同的内存地址,这两个进程仍然在物理内存的不同区域中具有不同的内存。操作系统通过其虚拟内存管理器和页面转换来处理这个问题。每个进程都有自己的虚拟地址空间,操作系统根据需要将各个部分透明地映射到物理内存。