c alloca 函式的實現

2021-06-29 05:29:37 字數 1383 閱讀 8013

c 語言裡有乙個 alloca 函式,可以在堆疊上分配一塊記憶體,當前函式退出時,由於系統堆疊指標的調整,這塊記憶體會被自動**。

alloca 的函式原型是

void *

alloca(size_t size);

今天,在各種程式設計文件中已經不太提倡使用了。因為它有許多不安全因素。這裡暫且不討論。

另外,在 crt 庫里,通常還會提供乙個_alloca函式,供編譯器內部生成**使用。比如在 c99 標準中,允許程式設計師在堆疊上開啟變長陣列,gcc 其實就是通過_alloca分配的記憶體來實現這個特性的。

另外,當你分配為區域性變數陣列申請空間過大時,gcc 也會呼叫_alloca。(大概是因為 crt 在實現 alloca 時,附帶增加了一定的檢測功能,測試堆疊溢位)

這個週末,我手工寫了乙個_alloca,試著替換 crt 的實現(莫追究原因 :) )。一開始老不得要領,總是不能正常工作。

gcc 的這個_alloca是個內部函式,其呼叫協議不同於 alloca 。它的尺寸引數並不通過堆疊傳遞,而是直接通過暫存器。在 x86 上,就是 eax 。

返回值當然是通過 eax 送出,同時一併修改了堆疊暫存器 esp 。

經過多次程式崩潰,並用 gdb 對彙編**逐行分析,還看出了另外一點門道。

呼叫_alloca這個函式前,呼叫者並不需要對其它暫存器裡的資料安全負責。就是說,_alloca需要負責除 eax esp 之外的暫存器內的資料安全,不得破壞。(或許沒有這麼嚴格,我試著用了乙個 ecx ,並沒有出錯。但是破壞掉 edx 卻是一定會引起程式崩潰的)

如果開啟 gcc 的優化開關(我使用的 -o2 ,gcc 版本 3.4.5),編譯器有時候會**_alloca的行為,並以此來決定堆疊上區域性變數的分布(往往出現在**中以常量申請固定尺寸的大陣列的情況下)。_alloca的行為被認為是在堆疊上準確分配經過 4 位元組對齊後的 eax 內值大小的空間。不僅不能少分配,連多分配也是不允許的(否則會導致編譯器生成的**出錯)。

最後給出雲風的_alloca的實現。

.globl __alloca; 

__alloca:

subl $1,%eax

andl $0xfffffffc,%eax /* align to dword */

subl %eax,%esp

pushl (%esp,%eax) /* return addr */

movl %esp,%eax

addl $4,%eax

ret

函式實現 MySQL排名函式實現

現在有個需求對所有學生分數進行排名,並且列出名次。剛看到這個需求,我有點懵逼,完全沒有思路?為什麼難一點需求,我就不會做呢?去網上查詢資料,把所有實現都列出來,全部都要學會。建立乙個分數表s score create table s score id int not null auto increm...

memcpy函式的實現

前段時間去面試自己比較喜歡的乙個工作,面試的哥們讓我實現void memcpy void to,const void from,size t count 這個函式。沒做出來,掛了。感到非常不爽。回來研究了一下。找著了幾個不同版的實現,貼出來。首先對這個函式做一些說明。include void mem...

atoi函式的實現

atoi函式的實現 寫這個函式的實現的原因很簡單,而且也很容易,直接抄襲的庫中的原始碼。因為有朋友面試的時候遇到了,前幾天乙個哥們面intel的時候也被問到了,巧合的是今天看廣聯達的面試題再次遇到。一周之內看到三次,讓我不得不重視一下啊,畢竟自己也要開始面試題呀面試題了!其實這個函式比較容易實現,不...