C語言中使用的地址是真實的物理地址嗎?


設置程序基址固定:關閉程序基地址改變

在vs中編寫代碼如下:

#include <stdio.h>

int main()
{
int a = 5;
printf("a的內存地址是 %d", &a);
system("pause");
return 0;
}

編譯生成程序,找到vs生成的Test.exe文件,我們雙擊運行Test.exe,發現變量a的內存地址是1703668,

然后不關閉這個程序,再雙擊運行Test.exe,發現又運行起來一個程序,顯示a的內存地址是1703668。

如圖:

很奇怪啊,第一次運行時申請的變量a的內存地址是1703668,再次運行Test.exe時,內存地址1703668不是已經被占用了嗎,為什么第二個程序的變量a的內存地址還是1703668?

這說明C語言中,或者說所有的編程語言中使用的內存地址都不是真實的物理地址,而是虛擬地址。

 

虛擬地址:CPU啟動保護模式后,程序運行在虛擬地址空間中。

PS:不是所有程序都運行在虛擬地址中。CPU啟動時是運行在實模式下的,Bootloader以及內核在初始化頁表之前並不使用虛擬地址,而是直接使用物理地址的。

 

如果CPU寄存器中的分頁標志位被設置,那么執行內存操作的機器指令時,CPU(准確來說,是MMU,即Memory Management Unit,內存管理單元)會自動根據頁目錄和頁表中的信息,把虛擬地址轉換成物理地址,完成該指令。
比如 mov eax,[004227b8h] ,這是把地址004227b8h處的值賦給寄存器的匯編代碼,004227b8這個地址就是虛擬址。CPU在執行這行代碼時,發現寄存器中的分頁標志位已經被設定,就自動完成虛擬地址到物理地址的轉換,使用物理地址取出值,完成指令。對於Intel CPU 來說,分頁標志位是寄存器CR0的第31位,為1表示使用分頁,為0表示不使用分頁。對於初始化之后的 Win2k 我們觀察 CR0 ,發現第31位為1。表明Win2k是使用分頁的。
 
由此可知,雖然我們每次運行Test.exe得到的a的內存地址都是一樣的,但我們知道這是虛擬地址,每次運行時申請到的物理內存的地址肯定是不一樣的。
 
更多虛擬地址的問題參考:https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E5%9C%B0%E5%9D%80/1329947?fr=aladdin


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM