2011-07-30 19 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

'malloc'を置き換えると同じエラーが発生するので、allocaはここでは問題ではないと思います。 –

+1

なぜ構造体にスペースを割り当てるために 'alloca'を使う必要があると思いますか?スタック上にオブジェクト 'task T;を作成することができます。タスク* t =&T; 'それを行うだろう。 –

+0

する必要がない場合は 'alloca'を使用しないでください。これは標準ではなく、移植性がなく、スコープに関係なくスタックメモリを予約する動作は、多くの驚きの原因です。現代C(別名C99)は、それを置き換えるように設計された可変長アレイ(VLA)を有する。 Boが言っているように、スタック上に変数を1つだけ作成するためには、このようなことは絶対に使わないでください。これには本当に意味がありません。 –

答えて

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... 
関連する問題