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

Post on 14-Dec-2014

1.635 Views

Category:

Documents

7 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

TRANSCRIPT

程式設計師的自我修養

Chapter 10 記憶體

Shu-Yu Fu (shuyufu@gmail.com)

本章概述

本章討論程式執行時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?

程式的記憶體配置

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

程式的記憶體配置

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

堆疊與呼叫慣例

● 在i386下,esp暫存器指向堆疊頂端● 堆疊保存了一個函式呼叫所需要的維護資訊,

常被稱為堆疊框架﹙stack frame﹚或活動記

錄﹙activate record﹚○ 函式的傳回位址和參數○ 臨時變數○ 保存的上下脈絡

● ESP暫存器始終指向堆疊頂部,EBP﹙又稱為

框架指標Frame Pointer﹚指向函式活動記錄的一個固定位置。

堆疊與呼叫慣例

● 在i386下,esp暫存器指向堆疊頂端● 堆疊保存了一個函式呼叫所需要的維護資訊,

常被稱為堆疊框架﹙stack frame﹚或活動記

錄﹙activate record﹚○ 函式的傳回位址和參數○ 臨時變數○ 保存的上下脈絡

● ESP暫存器始終指向堆疊頂部,EBP﹙又稱為

框架指標Frame Pointer﹚指向函式活動記錄的一個固定位置。

呼叫一個函式

1. 把所有或一部分參數推入堆疊中,如果有其他參數沒有入堆疊,那麼使用某些特定的暫存器傳遞

2. 把當前指令的下一條指令的位址推入堆疊中3. 跳轉到函式體執行

呼叫一個函式

1. 把所有或一部分參數推入堆疊中,如果有其他參數沒有入堆疊,那麼使用某些特定的暫存器傳遞

2. 把當前指令的下一條指令的位址推入堆疊中3. 跳轉到函式體執行

函式的開始與結束

EBP

HIGH LOW

ESP

函式的開始與結束

EBP

HIGH LOW

EBP

ESP

函式的開始與結束

HIGH LOW

EBP

ESP

EBP

函式的開始與結束

HIGH LOW

EBP

ESP

VAR

VAR

VAR

EBP

函式的開始與結束

HIGH LOW

EBP

VAR

VAR

VAR

REG

REG

ESP

EBP

函式的開始與結束

HIGH LOW

EBP

ESP

VAR

VAR

VAR

EBP

函式的開始與結束

HIGH LOW

EBP

ESP

VAR

VAR

VAR

EBP

函式的開始與結束

EBP

HIGH LOW

ESP

VAR

VAR

VAR

小知識

● 未初始化的區域變數的初始化成0xcccccccc● Hot Patch Prologue

More: 3.13 Hotpatch Support在GCC對應的實作為ms_hook_prologue

呼叫慣例

int foo(int n, float m){ int a = 0, b = 0; ...}

● 先推入n後推入m?● 呼叫方和被呼叫方對於呼叫的約定

○ 參數的傳遞順序﹙左先?右先?﹚和方式﹙堆疊?暫存器?﹚

○ 堆疊的維護方式,由呼叫方或被呼叫方維護○ 名稱修飾﹙name-mangling﹚的策略,對呼叫慣例進

行區分

列表

呼叫慣例 出堆疊方 參數傳遞 名稱修飾

cdecl 函式呼叫方 從右至左的順序推參數入堆疊

底線+函式名

stdcall 函式本身 從右至左的順序推參數入堆疊

底線+函式名+@+參數的位元組數,如函式int func(int a, double b)的修飾名是_func@12

fastcall 函式本身 頭兩個DWORD(4位元組)類型或者占更少位元組的參數被放入暫存器,其他剩下的參數按右到左的順序推入堆疊

@+函式名+@+參數的位元組數

pascal 函式本身 從左至右的順序推參數入堆疊

較為複雜,參見pascal文件

更多的呼叫慣例

● 用於特殊場合naked call● C++更複雜的名稱修飾策略和thiscall

○ VC,this存放於ecx暫存器○ GCC,this是函式的第一個參數

函式傳回值傳遞

● eax是傳遞傳回值的通道● 大於4-byte的傳回值如何傳遞?

○ 5-byte ~ 8-byte採eax(low-byte)和edx(high-byte)聯合傳回

○ > 8-byte,用隱含參數+eax

● 可以不懂過程,但,要記得不要輕易傳回大尺寸的物件

● C++提出了傳回值最佳化﹙Return Value Optimization, RVO﹚,可以將某些場合下的物件複製減少1次

堆積與記憶體管理

● 為什麼需要堆積?○ 動態產生○ 堆疊上的資料在函式傳回時就會被釋放,那main()裡的

區域變數呢?

● 把配置和釋放做在作業系統核心○ 每次都要系統呼叫,效能太差

● 應用程式自行管理,多數的情況是執行階段程式庫管理

○ 配置○ 管理,堆積的分配演算法

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

Windows行程堆積管理

● VirtualAlloc()用來向系統申請空間,應用程式可以按照需要隨意使用。

● 堆積管理器﹙Heap Manager﹚實作了空間分配演算法。○ NTDLL.DLL︰HeapCreate﹑HeapAlloc﹑HeapFree﹑HeapDestroy

● 預設1MB,可透過連結器的/HEAP參數指定● 最大的一塊大約是1.5GB

堆積分配演算法

● 堆積只是程式向作業系統申請劃出來的一塊位址空間

● 如何管理一大塊連續的記憶體空間並按照需求分配﹑釋放空間。○ 空間串列○ 點陣圖○ 物件集區

空間串列

把堆積中各個空閒的區塊按照串列的方式連接起來,當使用者請求一塊空間時,可以遊走整個列表,直到找到合適大小的區塊並且將它拆分;當使用者釋放空間時將它合併到空閒串列中。

點陣圖

將整個堆積劃分為大量大小相同的區塊

﹙block﹚,當請求記憶體時,總是分配整數個的

空間。

物件集區

如果每一次分配的空間大小都一樣,依把整個堆積空間劃分為大量的小塊,每次請求的時候只需要找到一個小塊就可以了。

現實應用

● 堆積分配演算法往往採取多演算法複合而成● 以glibc來講,

○ < 64-byte︰物件集區○ < 512-byte︰物件集區和最佳適配演算法的最佳折衷○ < 128-KB︰最佳適配演算法○ > 128-KB︰mmap()

● More: glibc中malloc的详细解释

參考實作

● jemallochttp://www.canonware.com/jemalloc/

● nedmallochttp://www.nedprod.com/programs/portable/nedmalloc/

top related