2010-08-15 62 views
6

我讀了很多地方alloca已過時,不應使用和應使用可變長度數組。alloca是完全可替換的嗎?

我的問題是:alloca完全可以通過可變長度數組來替換嗎?

在我的特殊情況下我有一些看起來像這樣:

typedef struct { 
    int *value; 
    size_t size; 
    } some_type; 

void SomeExternalFunction(some_type); 

... 

void foo(){ 
    //What I thought to do 
    some_type bar; 
    bar.value=alloca(sizeof(int)*10); 
    SomeExternalFunction(bar); 

    //what should be done without alloca 
    some_type fizz; 
    int tmp[10]; 
    fizz.value=tmp; 
    SoemExternalFunction(fizz); 
} 

我缺少的東西,或這是一個實際的用好ALLOCA的?在這個例子中,假設我想要將值分配到堆棧上

+4

這實際上不是一個可變長度的數組......正如你指定了一個常量長度。而且......即使它*長度可變,我並沒有真正看到alloca在這裏購買了什麼,除了讓代碼的意圖稍微模糊。 (很顯然,如果你使用的編譯器不支持可變長度數組,你無需在兩者之間進行選擇) – Shog9 2010-08-15 19:17:59

+0

另請參閱:http://stackoverflow.com/questions/3452434/in-which- cases-is-alloca-useful(將根據標題重複,但我覺得你確實想要問別的東西......雖然不知道是什麼) – Shog9 2010-08-15 19:22:26

回答

13

VLA和alloca之間有一個重要區別:只要當前函數持續存在,內存alloca()返回有效。只要VLA的標識符保持在範圍內,VLA佔用的存儲器的有效期爲。例如,您可以在循環中分配內存(),並使用以外的內存,因爲在循環終止時標識符超出範圍,VLA將消失。這意味着,你可以用alloca()和足夠的堆棧空間來做到這一點:

typedef struct node { int data; struct node *next; }; 
void fun() 
{ 
struct node *n=0; 
int d; 
/* Now we are building a single-linked list on the stack! */ 
while(d=get_something()) { 
    struct node *x=alloca(sizeof(*x)); 
    x->next=n; 
    x->data=d; 
    n=x; 
} 
do_something_with(n); 
} // and the whole thing is deleted here.. 

你不能用VLA做到這一點。

+0

FWIW:這對兩個人來說都是一個很好的答案[哪些情況是alloca()有用?](http://stackoverflow.com/questions/3452434/in-which-cases-is-alloca-useful)和[有什麼區別alloca(n)和char x \ [n \]?](http://stackoverflow.com/questions/2614561/whats-the-difference-between-allocan-and-char-xn) – Shog9 2010-08-15 23:01:16

+0

這是一個很好的答案有關的差異,但你可能也想注意''alloca'的行爲基本上是實現定義的,因爲它沒有在任何(當前)標準中指定。 – 2010-08-16 05:43:35

+0

順便說一句,**有一種方法可以對VLA做同樣的事情:使函數遞歸併在最深層調用'do_something_with(n)'。 :-)實際上我有一個真實世界的使用,我還沒有實現:'/ lib/ld.so'的輕量級實現,它在堆棧上執行動態鏈接,以避免將'malloc'開銷帶入微小不使用它的程序。最後,當且僅當'libdl'尚未鏈接時,它纔會展開並放棄所有動態鏈接數據;否則它會從最深的遞歸級別調用'_start'。 – 2010-08-16 05:45:12

1

alloca可完全被mallocfree替代。這是一個更多的工作,但除非你非常小心,這是至關重要的。幾乎所有使用alloca或C99 vla的代碼都容易受到堆棧溢出攻擊,並且在很多實現中,它們可能導致特權提升。沒有可移植的方法來知道堆棧有多大或剩下多少堆棧空間(或者編譯器內部使用或進一步的函數調用可能需要多少額外開銷),所以您可以做的唯一合理的事情是使vla的/ alloca安全是對您所支持的數據大小(例如幾kb)施加極小的人爲限制。在這一點上,你可能只是使用普通的非變長自動對象...

+0

堆完全替代堆棧。不。 – 2016-09-07 03:46:48