2010-08-15 34 views
6

Tôi đã đọc khá nhiều nơi mà alloca đã lỗi thời và không nên được sử dụng và Mảng độ dài biến nên được sử dụng thay thế.Alloca có thể thay thế hoàn toàn không?

Câu hỏi của tôi là: alloca có thể thay thế hoàn toàn bằng mảng chiều dài thay đổi không?

Trong trường hợp đặc biệt của tôi, tôi có cái gì đó trông như thế này:

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); 
} 

Tôi có thiếu một cái gì đó hoặc đây là một sử dụng tốt thực tế của alloca? Cũng giả sử cho ví dụ này vì lý do nào đó tôi muốn cho giá trị được phân bổ trên ngăn xếp

+4

Đó không phải là mảng có độ dài thay đổi ... Như bạn đã chỉ định độ dài không đổi. Và ... Ngay cả khi nó * là * một chiều dài thay đổi, tôi không thực sự nhìn thấy những gì alloca mua bạn ở đây, khác hơn là làm cho ý định của mã hơi mơ hồ hơn. (Rõ ràng nếu bạn đang sử dụng một trình biên dịch không hỗ trợ các mảng độ dài biến đổi, bạn cũng không có sự lựa chọn giữa hai loại) – Shog9

+0

Xem thêm: http://stackoverflow.com/questions/3452434/in-which- trường hợp-là-alloca-hữu ích (sẽ là một bản sao dựa trên tiêu đề, nhưng tôi cảm thấy bạn đang thực sự cố gắng để yêu cầu cái gì khác ... không thể nói những gì mặc dù) – Shog9

Trả lời

13

Có sự khác biệt quan trọng giữa VLA và alloca: Bộ nhớ alloca() trả về là hợp lệ miễn là hàm hiện tại vẫn tồn tại. Tuổi thọ của bộ nhớ bị VLA chiếm giữ là hợp lệ miễn là số nhận dạng của VLA vẫn nằm trong phạm vi. Ví dụ, bạn có thể sử dụng bộ nhớ alloca() trong một vòng lặp và sử dụng bộ nhớ bên ngoài vòng lặp, VLA sẽ biến mất do mã nhận diện nằm ngoài phạm vi khi vòng lặp kết thúc. Điều này có nghĩa, bạn có thể làm điều này với alloca() và đủ không gian ngăn xếp:

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.. 

Bạn không thể làm điều này với VLAs.

+0

FWIW: đây sẽ là một câu trả lời tuyệt vời cho cả hai [Trong trường hợp nào là alloca() có ích?] (Http://stackoverflow.com/questions/3452434/in-which-cases-is-alloca-useful) và [Sự khác nhau giữa alloca (n) và char x \ [n \]?] (http://stackoverflow.com/questions/2614561/whats-the-difference-between-allocan-and-char-xn) – Shog9

+0

Đây là một câu trả lời tuyệt vời về sự khác biệt, nhưng bạn cũng có thể muốn cần lưu ý rằng hành vi của 'alloca' về cơ bản được thực hiện do nó không được chỉ định trong bất kỳ tiêu chuẩn (hiện hành) nào. –

+0

Nhân tiện, có ** là ** cách làm tương tự với VLAs: làm cho hàm đệ quy và gọi 'do_something_with (n)' ở mức sâu nhất. :-) Trên thực tế tôi đã có một thế giới thực sử dụng cho điều này, mà tôi chưa thực hiện: một thực hiện nhẹ của '/ lib/ld.so' mà thực hiện liên kết động trên ngăn xếp để tránh đưa chi phí' malloc' vào nhỏ các chương trình không sử dụng nó. Cuối cùng, nó sẽ giải phóng và loại bỏ tất cả các dữ liệu liên kết động nếu và chỉ khi 'libdl' chưa được liên kết; nếu không nó sẽ gọi '_start' từ mức đệ quy sâu nhất. –

1

alloca hoàn toàn có thể thay thế bằng mallocfree. Đó là một công việc ít hơn một chút nhưng trừ khi bạn đang rất cẩn thận, đó là điều cần thiết. Gần như tất cả các mã sử dụng alloca hoặc C99 vla đều dễ bị tấn công tràn ngăn xếp và trong nhiều triển khai, chúng có thể dẫn đến độ cao đặc quyền. Không có cách nào để biết khoảng trống lớn hay bao nhiêu không gian ngăn xếp (hoặc có thể cần bao nhiêu chi phí vượt quá kích thước được yêu cầu để sử dụng nội bộ của trình biên dịch hoặc các cuộc gọi chức năng), vì vậy điều duy nhất bạn có thể làm làm cho vla's/alloca an toàn áp dụng các giới hạn nhân tạo cực nhỏ đối với kích thước dữ liệu bạn hỗ trợ (ví dụ: một vài kb). Tại thời điểm này, bạn cũng có thể chỉ sử dụng các đối tượng tự động không thay đổi độ dài ...

+0

Heap là hoàn toàn thay thế ngăn xếp. Không. –

Các vấn đề liên quan