1 2 3 4 5 6 7 8 9 10 | //~ test.cpp #include <stdio.h> int a; int main() { printf("%p\n", &a); sleep(30); return 0; } |
1 2 3 4 5 6 7 | $ gcc test.cpp -otest $ ./test& $ 0x804a024 $ ./test& $ 0x804a024 $ ./test& $ 0x804a024 |
对可执行文件test,不同的执行实例产生的输出为什么是一样的呢?为什么呢?难道一直以来我对虚拟地址空间的理解都是错误的?另外,如果int a是局部变量,输出就不同。
你好!除了代码,此处没有多少原创之物,皆为本人搜集、整理、总结之记录与心得,欢迎转载分享!转载时请尽量注明出处,将不胜感激。祝你健康、快乐!
是不是连续进行的实验?关机重试行不?
正因为a是在栈上分配的,a的地址才不变。你可以试试从堆上分配试试,每次分配得到的地址应该很难不同才对。
函数执行时会压栈,首先是函数地址,其次是一些附加的信息,再接着就是变量了。所以说a的相对地址一直没变,所以你得到的地址一直没变。
这里说的是,几个程序同时运行啊!
Boluor的这个说法是错的。
好囧,没仔细看,以为是一个程序多次运行呢。
那也不对吧。linux下如何对待进程不太了解,但是32位OS这块应该都类似吧。Win32下面每个进程都是独立的地址空间,不管是几个程序同时运行还是一个程序独立运行多次,全局变量的地址都不会改变,因为不同进程的地址空间是完全彼此独立的,互不影响。
按照Sandy的说法,程序的每次运行,都可以被加载到同一位置?比如Linux里面,用户程序的虚拟地址都是从0×08048000算起,所有的这些用户程序都被加载到这里?我对地址空间“独立”的理解有偏差。
囧。。
我对函数的执行还是很了解的。这里的问题应该在于,虚拟空间中内核、堆、栈、动态库等的分布和使用有关。
因为a是全局变量,在编译期就确定了地址,所以自然不变。
来说下程序中的几种不同变量的分配方式吧:
1、全局分配:全局变量以及各种static变量。在编译的时候就已经分配好了空间,一般位于专门的数据段中,相对地址不会发生任何改变。
2、栈上分配:所有的局部变量都在栈上分配,进入函数时压栈分配得空间,离开函数时弹栈空间自动得到释放。由于栈顶的位置是不固定的因此局部变量的地址常常发生变化。
3、堆上分配:各种动态分配方式(malloc、new等)都是在堆上进行分配,分配前进行记录,使用完毕后需要手工进行回收。堆的状态也是不确定的,因此堆上分配的变量的地址就更加不确定了。
这个问题开始明朗了。32为系统中,以Linux为例,每个用户进程都可以使用相同的0~3G的地址空间,但彼此之间却又是独立的,即相同的虚地址被映射到不同的物理地址上。但进程通讯时使用的是内核空间。
但是,栈和堆也都是在0~3G地址内的呀,为什么他们跟正常的数据段有区别呢?而且在堆上申请的空间地址总是相差4K(一个页面)的整数倍。
全局变量是在数据段中的,编译器确定好了的地址,加载的时候只是简单的映射到内存上去而已,不会有任何改变。
但是堆和栈都是在运行期动态改变的,不确定的。虽然都在用户内存中,彼此独立,但是其状态是不断变化的,因此地址常常会不同。
也就是说可以相同了?
就像掷2个色子,如果他们点数一样,没必要分析这是否有特殊的含义
猴哥我拿你的写记录册了
Nani?