执行时的C程序
數據和代碼
編程語言理論經典對立之中的一個就是代碼和數據的差別。有些語言如LISP把兩者視為一體,其它語言如C語言則維持兩者的差別。編譯絕大部分工作都跟翻譯代碼有關,必要的數據存儲管理的絕不部分都在執行時進行。
學習執行時能夠有三個優點,有助于優化代碼。獲得最佳效率,有助于理解更高級的材料。陷入麻煩的時候。能夠更easy的分析問題。
段(Segments)
ELF:(原意為Extensibla Linker Format,可擴展鏈接器格式,如今代表Executable and Linking Format,可執行文件和鏈接格式),存在于絕大多SVr4實現。
COFF:(Common Ojbect-File Format,普通目標文件格式)。存在于其它系統中。
上述兩種不同的格式有一個共同的概念,段。段的概念和非常多都相關,單就目標文件而言,段就是指二進制文件里簡單的區域,里面保存了和某種特定類型(如符號表條目)相關的信息。
術語Section也被廣泛使用。section是ELF文件里的最小組織單位。一個段一般包含幾個section。
上述段的概念是UNIX中的。和Intel X86架構的段全然沒有關系。UNIX中段就表示一個二進制文件的內容塊,intel X86中段表示一種設計的結果,在這樣的設計中,地址空間并非一個總體,而是分成64k大小的區域,稱之為段,這樣的設計也是情非得已,為了向下兼容以前的芯片。
a.out的結構
下圖顯示了編譯器和連接器分別在這些段中寫入了什么東西
BSS段是“Block Started by Symbol(由符號開始的塊)”的縮寫。它是舊式IBM704匯編程序的一個偽指令,UNIX借用了這個名字。至今仍然沿用。有些人喜歡把它記作“Better Save Space(更有效的節省空間)”,由于BSS段僅僅保存沒有值得變量,所以其實并不須要保存這些變量的映象。執行時所須要的BSS段的大小記錄在目標文件里。但BSS段不像其它段。它并不占用目標文件的不論什么空間
能夠使用size命令和nm程序來查看程序各個部分的大小
操作系統之于a.out
為什么要用段來組織,由于段能夠方便的映射到鏈接器。在執行時能夠直接加載。加載器僅僅須要提取文件里每一個段的映像。段在正在執行的程序中是一塊內存區域,每一個區域有特定的目的。
文本段包含程序的指令
數據段包含經過初始化的全局變量和靜態變量以及它們的值,BSS段的大小從可執行文件里得到。然后鏈接得到這個大小的內存塊。緊跟數據塊之后,這塊內存進入程序后所有清零。
C語言執行時系統之于a.out
執行時數據結構包含,堆棧、活動記錄、數據和堆等
- 堆棧段:主要有三個用途。和函數以及表達式有關。
除了遞歸調用,堆棧并非必須的。在大多數CPU中,堆棧是向下增長的,也就是朝著低地址方向生長。
- 為函數內部的局部變量提供存儲空間
- 函數調用過程中,保持一些維護性信息,稱為堆棧結構或者過程活動記錄
- 暫存區,非常長的算數表達式
和C++不同。C執行時函數個個短小精悍,使得C非常高效
C語言不同意在函數中定義函數,也就是函數不能嵌套定義。
setjmp和longjmp
以上兩個命令是C語言獨有的,通過操縱過程活動記錄實現的。
- setjmp(jmp_buf j)必須首先被調用。它表示使用變量j記錄如今的位置,函數返回0;
- longjmp(jmp_buf j,int i)能夠接著被調用。它表示回到j所記錄的位置,讓他看上去像剛從setjmp函數返回一樣??墒呛瘮捣祷豬。使代碼知道它實際上是通過longjmp返回的。
- 當使用longjmp時。j的內容被銷毀
- setjmp保存了一份程序計數器和當前的棧頂指針,也能夠保存一些初始值,longjmp恢復這些初始值。
- 和goto不同,第一,goto不能跳出C語言的函數;第二。longjmp僅僅能回到以前到過的地方。
- 須要注意的是。保證局部變量在longjmp過程中一直保持它的值得唯一可靠辦法就是把它聲明為volatile。
- 兩者組合最大用途是錯誤恢復。僅僅要還沒從函數返回,一旦發現一個不可恢復的錯誤,就能夠把控制流轉移到主輸入循環。能夠用它來從一串非常深的代碼中馬上返回,提防潛在的危急代碼。
眼下C++已經支持了異常系統
- 和goto一樣。不是必要的情況下不要使用它們。
UNIX和MS-DOS的堆棧段
- 在UNIX中,當進程須要很多其它空間的時候,堆棧會自己主動生長。
- DOS中,在建立可執行文件時,堆棧大小必須同一時候確定,并且它不能在執行時增長。Stack overflow是常見的堆棧溢出錯誤。
實用的C語言工具
Reference
C專家編程
轉載于:https://www.cnblogs.com/brucemengbm/p/7268517.html
總結
- 上一篇: Swift函数
- 下一篇: redis--Sentinel