printf()在c中以%p格式打印的地址是哪个?

BSa*_*nke 15 c linux gcc virtual-address-space

我的代码如下:

#include<stdio.h>

int glob;

int main(void)
{
   int a;
   printf("&a is : %p \n", &a);
   printf("glob is : %p \n", &glob);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

上述程序的输出是:首先运行:

&a is : 0x7fff70de91ec
glob is : 0x6008f4
Run Code Online (Sandbox Code Playgroud)

第二轮:

&a is : 0x7fff38c4c7ac
glob is : 0x6008f4
Run Code Online (Sandbox Code Playgroud)

我正在研究虚拟和物理地址.我有以下问题:

  1. 哪个是变量"a"的打印地址(物理/虚拟)?
  2. 如果它是虚拟的那么,它在同一程序的每次运行中如何变化?据我所知,编译器在编译时为变量提供虚拟地址?
  3. 为什么全局变量的地址在每次运行程序中都是常量?

在Linux上执行此程序:2.6.18-308.el5 x86_64 GNU/Linux

编译使用:gcc版本4.1.2 20080704(Red Hat 4.1.2-52)

Som*_*ude 15

两个地址都是虚拟的.

现代系统使用堆栈随机化来防止所谓的堆栈粉碎攻击,这就是本地变量可以在每次运行时更改其位置的原因.但是,全局变量存储在可执行文件中,并且每次都以相同的偏移量加载.

  • 值得注意的是,某些其他操作系统和一些更具安全性的Linux发行版具有PIE(位置无关的可执行文件),并且那些全局变量的地址也将发生变化. (7认同)

Dav*_*rra 6

在程序中看到的地址始终是虚拟的,OP描述的行为是Linux对策,以避免缓冲区溢出攻击.

只是为了尝试,你可以用它来禁用它

sysctl -w kernel.randomize_va_space=0
Run Code Online (Sandbox Code Playgroud)

然后再次运行您的程序并观看.

全球性的存在于另一个记忆空间中,从一个黑客的观点来看,它是无害的.那是因为它不是每次都是随机的.


rko*_*egi 5

您的程序将始终只看到虚拟地址。

真实地址仅适用于内核模式下的虚拟内存管理器。

全局变量具有相同的地址(除非您在其前面放置其他变量),因为它是在数据段中创建的。

局部变量总是在堆栈上创建。

  • 局部变量也可以是“静态”...:) (2认同)