2015-10-08 50 views
-4

分配我真的很好奇alloca()功能是如何工作的,因此,如下我寫了一個簡單的測試程序:哪裏變長數組/ ALLOCA堆棧

int test() { 
    int a = 0; 
    int e; 
    char tmp2[a]; //alloca 
    int d; 
    char* tmp3 = new char[2]; 
    tmp2[100] = 1; 
    return 0; 
} 

int main(int argc, char** argv) { 
    test(); 
    return 0; 
} 

根據該文件,alloca()將分配內存在堆棧中。我使用gdb運行程序,並找出(char*)&tmp2 - (char*)a = -44,這意味着它們之間有44個字節,而地址e-a,d-etmp3-d之間的距離是4個字節。我真的無法理解編譯器如何在堆棧中分配一個可變長度的數組,並希望有人能告訴我這44個字節的含義。

+3

您的代碼不包含對稱爲'alloca'的函數的調用。但是,它包含'new',它動態地分配內存。這不會發生在「堆棧」上。 – Andrew

+3

你的測試根本不會調用'alloca()'... –

+0

非常抱歉,我使用\「char tmp2 [a];」它分配一個可變長度的數組,與alloca相同 –

回答

3

alloca()不是標準的一部分。它被認爲是編譯器/機器相關的。因此,內在屬性只屬於實現。

話雖如此,如果我們談論的x86機器,然後堆放操作是通過使用專用堆棧指針寄存器來完成 - sp/esp/rsp(16/32/64位碼),其中包括最後一個字的地址/ dword/qword推入堆棧。爲了保留更多的內存,我們只需從sp寄存器中減去一些值即可。

因此x86中的「典型」alloca(x)實現只是一個單一的CPU指令:sub sp, x

+1

但是在我的測試中,x只有0,所以爲什麼要移動44個字節 –

+1

@TruongHua看看編譯器的彙編輸出,看看它產生了什麼指令。 – TartanLlama

+0

@TruongHua只有反彙編才能顯示真相。編譯器沒有義務保持聲明的順序。 – Matt

1
char tmp2[a]; 

其中a是非恆定整數,使用稱爲可變長度數組,或VLA個C99特徵。

該功能在標準C++中不可用,儘管它是g ++編譯器在不符合模式下支持的語言擴展。

未詳細說明如何爲VLA分配內存。它可能在機器堆棧上,如alloca,或者它可能是動態分配的內存。