要回答上述問題,必須首先了解這樣一個問題“我們寫的代碼是如何被計算執行的?”。
這就涉及到了程序的編譯和裝載。這里我們簡單的說一下大致流程,代碼首先要經過編譯器(gcc/g++)編譯鏈接后生成可執行文件,隨后系統將可執行文件加載到內存,接下來CPU從內存中讀取指令,數據等信息執行該程序。
從以上流程中,我們可以看出我們的代碼經歷了三個階段:代碼---》可執行文件----》進程(運行著的程序)。我們先給出正確答案:標識符只存在與代碼和可執行程序階段,在進程階段是不存在的(也就是說在內存中不存在標識符)。
眾所周知代碼文件中肯定存在標識符。
1. 可執行文件中的標識符
接下來,我們分析可執行程序中是否存在標識符?首先我們了解一下可執行程序大致的文件結構。(詳細內容請看http://www.lxweimin.com/p/a9dfd55792e7)
目標文件詳細內容與結構.jpg
在可執行文件中,標識符存儲在了.shstrtab中
.shstrtab: 字符串表。在ELF文件中用到了很多字符串,比如段名,變量名等。當 ELF 文件的其它部分需要引用字符串時,只需提供該字符串在字符串表中的位置索引即可。
這樣做的目的就是為了調試程序,因此我們可以在調試器中看到標識符與其值之間的對應關系。
2.標識符是否會被加載到內存中?
答案當然是表示符不會加載到內存中。首先,先看一段代碼
int g(int x)
{
return x + 2017;
}
編譯后:
g:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
addl $2017, %eax
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size g, .-g
.globl f
.type f, @function
以“.”開頭的行代表鏈接有關的代碼,刪除后是:
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $2017, %eax
popl %ebp
ret
查看這一看:
movl 8(%ebp), %eax
這一行就表示將x從棧里取出來放在eax中。X的表示形式為棧址(%ebp)加偏移量。根本沒有出現x(g其實也是不存在的,這只是個tag,為了簡寫匯編程序的。變成機器碼后就相當于沒有g了)
總結:標識符的根本就是不存在的啊,這些標識符就是棧址 + 偏移的形式。