2011-07-30 29 views
0

C一直都是個謎!如何使用alloca來分配C函數指針?

我正在實施一個工作人員線程執行模型,其中我試圖使用alloca作爲更快的內存分配選項。嘗試通過使用alloca存儲在堆棧上的函數指針來執行代碼時,我遇到了一個奇怪的分段錯誤。

這裏的一個牙籤代碼,這導致了類似的段故障:

#include <stdlib.h> 
#include <stdio.h> 

typedef void* (*foo)(void*); 

typedef struct task 
{ 
    foo f; 
} task; 

void *blah(void* v) 
{ 
    printf("addr:%p\n", &v); 
    return v; 
} 

int main() 
{ 
    void *queue[10]; 

    task *t = (task*) alloca (sizeof(task)); 
    // No null check, excuse me! 
    t->f = blah; 

    queue[0] = (void*)t; 
    char string[10] = "Bingo!"; 
    char *c = &string[0]; 

    task *tnew = (task*)&queue[0]; 
    tnew->f((void*)c); 

    return 0; 
} 

當我執行上面的代碼我得到在tnew-> f()的線段故障。 GDB回溯對我幫助不大。

請在上面的代碼中解釋錯誤..我第一次使用alloca。

非常感謝!

+2

我不認爲alloca是這裏的問題,因爲用'malloc'替換導致相同的錯誤。 –

+1

爲什麼你認爲你需要使用'alloca'來爲結構分配空間。你可以在棧上創建一個對象,'task T;任務* t =&T;'會做。 –

+0

如果不需要,不要使用'alloca'。它是非標準的和不可移植的,其預留堆棧內存的行爲與範圍無關,是許多意外事件的來源。現代C,又名C99,具有可變長度陣列(VLA),可以替代它。但正如Bo所說,從來沒有用過這樣的東西在堆棧上創建一個變量。這真的沒有意義。 –

回答

7

改變這一行:

task* tnew = (task*)&queue[0]; 

task* tnew = (task*)queue[0]; 

由於queue[0]已經是指針;你不需要知道它的地址。你在blah裏面有同樣的問題。你的printf不會崩潰,但它會打印出指針的地址,而不是指針的值,這可能不是你想要的。

+0

非常感謝!你是絕對正確的。那就是現場。 :-) – nandu

+0

如果您希望編譯器爲您發現這種問題,請將所有的強制轉換出來,並給予'隊列'正確的類型而不是void * []。 –

0

也許你可能也想傳遞參數「v」?

t->f = blah; // BAD 

t->f = blah (SOMETHING); // Better...