程式設計師的自我修養 Chapter 10 記憶體

2,901 views

Published on

2 Comments
5 Likes
Statistics
Notes
No Downloads
Views
Total views
2,901
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
62
Comments
2
Likes
5
Embeds 0
No embeds

No notes for slide

程式設計師的自我修養 Chapter 10 記憶體

  1. 1. 程式設計師的自我修養 Chapter 10 記憶體Shu-Yu Fu (shuyufu@gmail.com)
  2. 2. 本章概述本章討論程式執行時Stack和heap的配置!● 藉由觀察stack的變化導出Calling convention, 然後函式如何傳遞返回值!● 除了比較heap在Linux和Windows上的實作外, 我們還會討論heap管理演算法!● PS︰記得參考這篇產生你的assembly code+C code How to get gcc to interleave assembly output with original source code Using GCC to produce readable assembly?
  3. 3. 程式的記憶體配置Flat memory model or linear memory model refers to a memory addressingparadigm in low-level software design such that the CPU can directly (and sequentially/linearly)address all of the available memory locations without having to resort to any sort of memorysegmentation or paging schemes.int *p = (int *)0x12345678;++*p;● 記憶體空間"預設"的區域︰ ○ 堆疊﹙stack﹚ ○ 堆積﹙heap﹚ ○ ELF / dynamic libraries / reserved
  4. 4. 程式的記憶體配置Flat memory model or linear memory model refers to a memory addressingparadigm in low-level software design such that the CPU can directly (and sequentially/linearly)address all of the available memory locations without having to resort to any sort of memorysegmentation or paging schemes.int *p = (int *)0x12345678;++*p;● 記憶體空間"預設"的區域︰ ○ 堆疊﹙stack﹚ ○ 堆積﹙heap﹚ ○ ELF / dynamic libraries / reserved
  5. 5. 堆疊與呼叫慣例● 在i386下,esp暫存器指向堆疊頂端● 堆疊保存了一個函式呼叫所需要的維護資訊, 常被稱為堆疊框架﹙stack frame﹚或活動記 錄﹙activate record﹚ ○ 函式的傳回位址和參數 ○ 臨時變數 ○ 保存的上下脈絡● ESP暫存器始終指向堆疊頂部,EBP﹙又稱為 框架指標Frame Pointer﹚指向函式活動記錄的 一個固定位置。
  6. 6. 堆疊與呼叫慣例● 在i386下,esp暫存器指向堆疊頂端● 堆疊保存了一個函式呼叫所需要的維護資訊, 常被稱為堆疊框架﹙stack frame﹚或活動記 錄﹙activate record﹚ ○ 函式的傳回位址和參數 ○ 臨時變數 ○ 保存的上下脈絡● ESP暫存器始終指向堆疊頂部,EBP﹙又稱為 框架指標Frame Pointer﹚指向函式活動記錄的 一個固定位置。
  7. 7. 呼叫一個函式1. 把所有或一部分參數推入堆疊中,如果有其他 參數沒有入堆疊,那麼使用某些特定的暫存器 傳遞2. 把當前指令的下一條指令的位址推入堆疊中3. 跳轉到函式體執行
  8. 8. 呼叫一個函式1. 把所有或一部分參數推入堆疊中,如果有其他 參數沒有入堆疊,那麼使用某些特定的暫存器 傳遞2. 把當前指令的下一條指令的位址推入堆疊中3. 跳轉到函式體執行
  9. 9. 函式的開始與結束HIGH LOW EBP ESP
  10. 10. 函式的開始與結束HIGH LOW E B P EBP ESP
  11. 11. 函式的開始與結束HIGH LOW E B P ESP EBP
  12. 12. 函式的開始與結束HIGH LOW E V V V B A A A P R R R ESP EBP
  13. 13. 函式的開始與結束HIGH LOW E V V V R R B A A A E E P R R R G G ESP EBP
  14. 14. 函式的開始與結束HIGH LOW E V V V B A A A P R R R ESP EBP
  15. 15. 函式的開始與結束HIGH LOW E V V V B A A A P R R R ESP EBP
  16. 16. 函式的開始與結束HIGH LOW V V V A A A R R R EBP ESP
  17. 17. 小知識● 未初始化的區域變數的初始化成0xcccccccc● Hot Patch Prologue More: 3.13 Hotpatch Support 在GCC對應的實作為ms_hook_prologue
  18. 18. 呼叫慣例int foo(int n, float m){ int a = 0, b = 0; ...}● 先推入n後推入m?● 呼叫方和被呼叫方對於呼叫的約定 ○ 參數的傳遞順序﹙左先?右先?﹚和方式﹙堆疊?暫 存器?﹚ ○ 堆疊的維護方式,由呼叫方或被呼叫方維護 ○ 名稱修飾﹙name-mangling﹚的策略,對呼叫慣例進 行區分
  19. 19. 列表呼叫慣例 出堆疊方 參數傳遞 名稱修飾cdecl 函式呼叫方 從右至左的順序推參數 底線+函式名 入堆疊stdcall 函式本身 從右至左的順序推參數 底線+函式名+@+參數的位元 入堆疊 組數,如函式int func(int a, double b)的修飾名是 _func@12fastcall 函式本身 頭兩個DWORD(4位元組) @+函式名+@+參數的位元組 類型或者占更少位元組 數 的參數被放入暫存器,其 他剩下的參數按右到左 的順序推入堆疊pascal 函式本身 從左至右的順序推參數 較為複雜,參見pascal文件 入堆疊
  20. 20. 更多的呼叫慣例● 用於特殊場合naked call● C++更複雜的名稱修飾策略和thiscall ○ VC,this存放於ecx暫存器 ○ GCC,this是函式的第一個參數
  21. 21. 函式傳回值傳遞● eax是傳遞傳回值的通道● 大於4-byte的傳回值如何傳遞? ○ 5-byte ~ 8-byte採eax(low-byte)和edx(high-byte)聯合 傳回 ○ > 8-byte,用隱含參數+eax● 可以不懂過程,但,要記得不要輕易傳回大尺 寸的物件● C++提出了傳回值最佳化﹙Return Value Optimization, RVO﹚,可以將某些場合下的 物件複製減少1次
  22. 22. 堆積與記憶體管理● 為什麼需要堆積? ○ 動態產生 ○ 堆疊上的資料在函式傳回時就會被釋放,那main()裡的 區域變數呢?● 把配置和釋放做在作業系統核心 ○ 每次都要系統呼叫,效能太差● 應用程式自行管理,多數的情況是執行階段程式庫管理 ○ 配置 ○ 管理,堆積的分配演算法
  23. 23. Linux行程堆積管理● brk系統呼叫,設定行程資料區段的結束位址 int brk(void * end_data_segment);● mmap系統呼叫,申請一段虛擬位址空間 void * mmap(void * start, // 起始位址 size_t length, // 長度 int prot, // 權限﹙讀/寫/執行﹚ int flags, // 類型﹙檔案/匿名﹚ int fd, // fd...XD off_t offset); // 偏移量● malloc一次能夠申請的最大空間是多少? ○ Demo
  24. 24. Windows行程堆積管理● VirtualAlloc()用來向系統申請空間,應用程式 可以按照需要隨意使用。● 堆積管理器﹙Heap Manager﹚實作了空間分 配演算法。 ○ NTDLL.DLL︰HeapCreate﹑HeapAlloc﹑HeapFree﹑HeapDestroy● 預設1MB,可透過連結器的/HEAP參數指定● 最大的一塊大約是1.5GB
  25. 25. 堆積分配演算法● 堆積只是程式向作業系統申請劃出來的一塊 位址空間● 如何管理一大塊連續的記憶體空間並按照需 求分配﹑釋放空間。 ○ 空間串列 ○ 點陣圖 ○ 物件集區
  26. 26. 空間串列把堆積中各個空閒的區塊按照串列的方式連接起來,當使用者請求一塊空間時,可以遊走整個列表,直到找到合適大小的區塊並且將它拆分;當使用者釋放空間時將它合併到空閒串列中。
  27. 27. 點陣圖將整個堆積劃分為大量大小相同的區塊﹙block﹚,當請求記憶體時,總是分配整數個的空間。
  28. 28. 物件集區如果每一次分配的空間大小都一樣,依把整個堆積空間劃分為大量的小塊,每次請求的時候只需要找到一個小塊就可以了。
  29. 29. 現實應用● 堆積分配演算法往往採取多演算法複合而成● 以glibc來講, ○ < 64-byte︰物件集區 ○ < 512-byte︰物件集區和最佳適配演算法的最佳折衷 ○ < 128-KB︰最佳適配演算法 ○ > 128-KB︰mmap()● More: glibc中malloc的详细解释
  30. 30. 參考實作● jemalloc http://www.canonware. com/jemalloc/● nedmalloc http://www.nedprod. com/programs/portable/nedmalloc /

×