c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?

加载到内存中不就会把另一个程序的指令覆盖了吗补充:是经过objdump以后,每条指令前面都有的那个地址,一般是0x400000左右,然后我还发现一些常数一般在0x600000左右,然后rsp栈顶指针一般是0x7fffffffff……

在操作系统的分配下,每个程序的实际地址都不同

c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?

把一个程序自己的代码、数据、堆栈看成一块完整的砖头。编译器就是造砖机,安排好这一块砖内部的结构。

裸奔的系统就这一块砖,不会发生相互覆盖的矛盾。

如果跑多任务,砖头就多了。但这时通常会引入操作系统来管理砖头。堆砌砖头时会给每块砖头不一样的起始坐标,确保不发生两块砖头占一个空间的情况。

早期的dos操作系统规定每块砖头高度不超过1M。编译器做出来的每块砖内部都是用偏移地址0000h—ffffh来区分单元,但是操作系统在往物理内存搬砖堆砌时,会给每块砖不同的段起始地址,和偏移地址加在一起才是物理地址。这样就不会发生重叠了。

当然这里也有编译器的功劳。编译器除了造砖,还会生成一个规格标签,用于通知操作系统这砖有多大多厚,让操作系统能好好堆砖不浪费空间。不同操作系统的这种规格标签格式不一样,因此windows程序是不能直接跑在linux下的。

后来的处理器出现了mmu,内存管理单元,程序的地址空间和物理地址空间的换算就更复杂了。但是保证不同程序各自空间不发生覆盖还是基本要求。

一个程序能覆盖别的程序空间,大概是病毒恶意代码才做的事情。cpu的安全特性越来越强,这种情况很少见了吧。

c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?

这涉及到操作系统知识,而且这个似乎没写在教科书上。

C编译后的指令都写在可执行文件之中。所有指令地址都是从文件某个偏移开始的。

当操作系统加载可执行程序并分配进程时,会为每个进程分配自己的独有内存空间。

虽然两个进程的某个内存地址数值相同,但他们物理内存地址绝不相同,进程的独立内存空间只是对物理内存的一种映射关系而已。

再回到可执行指令加载话题。程序一般都有很多跳转指令,它需要一个绝对内存地址,这个就要求操作系统在加载进程时,分配一个进程基础地址,然后在所有跳转指令,以及某些全局变量地址中根据基础地址调整内存地址。

不只是进程加载,其实动态库加载都会涉及跳转指令地址调整问题。

当然,早期系统,例如dos系统,没有这套机制,它的程序内存地址都可以看作物理地址。但就现代操作系统来说,都是有这套机制的。

c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?

通俗说,这好比各个小区都有101房号,会冲突不。

程序的地址并不是绝对地址,而是相对地址。操作系统给运行的程序先安排起始地址存放在某寄存器中,再从相对地址0开始安排程序的相对地址。

安排的程序起始地址不同,不会冲突的。

绝对地址=起始地址+相对地址

c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?

虚拟内存空间了解下,每个程序有自己的虚拟内存空间,真正的物理地址要通过MMU单元翻译虚拟地址得到,MMU映射时每个程序物理地址起始空间不同,不同程序相同的虚拟地址得到的物理地址自然不同。

c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?

编译之后还有链接过程。单纯的编译会出现你说的这个情况,但是链接会把不同文件放置在不同地址上

内容仅供参考,如果您需解决具体问题(尤其法律、医学等领域),建议您详细咨询相关领域专业人士。

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请与我们联系,我们将及时删除。

相关推荐