首页 文章

变量地址之间的差异

提问于
浏览
3

为什么每次运行程序时变量地址都会有不同的特定数量(如“printf(”%d%d \ n“,&a,&b);” . 它将在一次运行中打印“1000 988”,“924 912“在另一个,”1288 1276“,依此类推)?在每个变量声明后,编译器是否会占用一定量的内存而无法写入任何内容?如果是,它依赖于什么?在我的程序中使用一些变量,它们之间的最小差异是12个字节,它达到212.这是唯一一个差异不是十二的倍数的情况(在其他情况下它是24,36或48)字节) . 那背后有什么理由吗?由于我的变量是int类型(在我的系统中占用4个字节),我的变量地址之间的差异是否可以小于12(例如4)?那些地址差异取决于变量类型吗?如果是,以什么方式?先感谢您!

3 回答

  • 2

    今天大多数操作系统使用地址空间布局随机化,以使编写某些类型的恶意软件变得更加困难 . (将代码写入内存然后尝试让程序将控制交给它的那种;现在必须猜测要使程序跳转到哪个地址 . )因此,变量不会在同一地址每次运行程序 .

    根据变量的类型,分配方式以及运行的操作系统和体系结构,变量的大小和对齐方式会有所不同 . 编译器和运行时可能会或可能不会总是将它们放在四个,八个或十六个字节的边界上 . 例如,x86_64函数调用ABI总是在16字节边界上启动函数的堆栈帧,并且 malloc() 的某些实现总是返回可被16整除的地址,因为这需要在某些CPU上存储向量 .

    如果您想知道编译器正在做什么,您可以尝试编译到汇编 . 在gcc或clang上,您可以使用 -S 标志执行此操作 .

  • 0

    如果你问为什么变量的内存地址在不同的可执行运行之间有所不同,那么答案就是ASLR,它的存在使得在代码中利用安全问题变得更加困难(参见https://en.wikipedia.org/wiki/Address_space_layout_randomization) .

    如果禁用ASLR,每次运行可执行文件时,您将获得给定变量的相同地址 .

    另见Difference between gdb addresses and "real" addresses?

  • 4

    您的链接器(在某种程度上,您的编译器)列出了应用程序的地址空间 . 链接器通常基于某个地址(例如,零)构建可重定位图像 . 显然,您的加载程序在运行时将可重定位图像放在不同的位置 .

    在每个变量声明后,编译器是否会占用一定量的内存而无法写入任何内容?

    通常没有UNLESS,下一个变量需要对齐 . 变量通常与变量大小的倍数的地址对齐 .

    听起来你的编译器正在为你根本不考虑的东西分配内存 .

相关问题