char *ptr = (char*) malloc(40);
printf("%u",ptr);
56737856 (some output)
现在,如果我没有错的话,我们上面看到的输出不是一个物理地址,而是来自虚拟地址空间。我说的对吗?
有办法看到实际的物理地址吗?或者反之亦然(如果我上面的假设是错误的),malloc的所有内部实现都必须使用jemalloc
算法吗?
在用户空间应用程序中看到的所有地址都是虚拟地址。
物理地址只与内核有关。从虚拟地址到物理地址的映射是复杂的,如果:
- 并不是所有的虚拟地址都有物理地址。(例如,未映射、惰性零填充或交换出的页面没有物理地址。)
- 物理地址可能会在没有警告的情况下发生变化(例如,如果一个页面被换出和换回,或者如果一个共享页面被复制)。
除了一些非常不寻常的情况(主要是与硬件有关),您不应该关心物理地址。
是的,在具有虚拟内存的平台上,它是进程地址空间中的地址,即它是虚拟内存中的地址。在这样的系统中,在典型的应用程序级别上,RAM中的实际物理地址没有任何意义——即使当时已经知道了,它也可以随时改变。物理RAM地址超出了您的控制范围。因此,在典型的应用程序级别,当人们谈论"物理地址"时,他们通常指的是你打印的东西——进程地址空间中的地址,即虚拟地址。
就是不要使用%u
到printf
的指针。使用%p
。或者至少将指针转换为适当大小的无符号整数类型,并为该类型使用格式说明符。
有办法看到实际的物理地址吗?
在真实模式下的x86架构中,没有内存保护,您可以返回实际的物理地址,因此您可以做诸如覆盖0x0地址之类的事情。
这是一段来自"内存管理:C/c++中的算法和实现"的代码片段,它可以使运行DOS的计算机崩溃:
void main()
{
unsigned char* ptr;
int i;
ptr = (unsigned char *)0x0;
for(i = 0; i < 1024; i++)
{
ptr[i]=0x0;
}
return;
}
请允许我引用维基百科:
实模式不支持内存保护、多任务处理或代码特权级别。发布前80286引入了保护模式,实模式是唯一的x86 cpu的可用模式。为了倒退的利益所有x86 cpu复位时都以实模式启动。