c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?
在操作系统的分配下,每个程序的实际地址都不同
c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?
把一个程序自己的代码、数据、堆栈看成一块完整的砖头。编译器就是造砖机,安排好这一块砖内部的结构。
裸奔的系统就这一块砖,不会发生相互覆盖的矛盾。
如果跑多任务,砖头就多了。但这时通常会引入操作系统来管理砖头。堆砌砖头时会给每块砖头不一样的起始坐标,确保不发生两块砖头占一个空间的情况。
早期的dos操作系统规定每块砖头高度不超过1M。编译器做出来的每块砖内部都是用偏移地址0000h—ffffh来区分单元,但是操作系统在往物理内存搬砖堆砌时,会给每块砖不同的段起始地址,和偏移地址加在一起才是物理地址。这样就不会发生重叠了。
当然这里也有编译器的功劳。编译器除了造砖,还会生成一个规格标签,用于通知操作系统这砖有多大多厚,让操作系统能好好堆砖不浪费空间。不同操作系统的这种规格标签格式不一样,因此windows程序是不能直接跑在linux下的。
后来的处理器出现了mmu,内存管理单元,程序的地址空间和物理地址空间的换算就更复杂了。但是保证不同程序各自空间不发生覆盖还是基本要求。
一个程序能覆盖别的程序空间,大概是病毒恶意代码才做的事情。cpu的安全特性越来越强,这种情况很少见了吧。
c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?
这涉及到操作系统知识,而且这个似乎没写在教科书上。
C编译后的指令都写在可执行文件之中。所有指令地址都是从文件某个偏移开始的。
当操作系统加载可执行程序并分配进程时,会为每个进程分配自己的独有内存空间。
虽然两个进程的某个内存地址数值相同,但他们物理内存地址绝不相同,进程的独立内存空间只是对物理内存的一种映射关系而已。
再回到可执行指令加载话题。程序一般都有很多跳转指令,它需要一个绝对内存地址,这个就要求操作系统在加载进程时,分配一个进程基础地址,然后在所有跳转指令,以及某些全局变量地址中根据基础地址调整内存地址。
不只是进程加载,其实动态库加载都会涉及跳转指令地址调整问题。
当然,早期系统,例如dos系统,没有这套机制,它的程序内存地址都可以看作物理地址。但就现代操作系统来说,都是有这套机制的。
c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?
通俗说,这好比各个小区都有101房号,会冲突不。
程序的地址并不是绝对地址,而是相对地址。操作系统给运行的程序先安排起始地址存放在某寄存器中,再从相对地址0开始安排程序的相对地址。
安排的程序起始地址不同,不会冲突的。
绝对地址=起始地址+相对地址
c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?
虚拟内存空间了解下,每个程序有自己的虚拟内存空间,真正的物理地址要通过MMU单元翻译虚拟地址得到,MMU映射时每个程序物理地址起始空间不同,不同程序相同的虚拟地址得到的物理地址自然不同。
c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?
编译之后还有链接过程。单纯的编译会出现你说的这个情况,但是链接会把不同文件放置在不同地址上
内容仅供参考,如果您需解决具体问题(尤其法律、医学等领域),建议您详细咨询相关领域专业人士。
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请与我们联系,我们将及时删除。