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