【问题标题】:How to use alloca to allocate C function pointers?如何使用 alloca 分配 C 函数指针?
【发布时间】:2011-10-16 08:53:12
【问题描述】:

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。

非常感谢!

【问题讨论】:

  • 我不认为 alloca 是这里的问题,因为替换为 malloc 会导致相同的错误。
  • 为什么你认为你需要使用alloca 来为结构分配空间。您可以在堆栈上创建一个对象,task T; task* t = &amp;T; 会这样做。
  • 如果没有必要,不要使用alloca。它是非标准且不可移植的,其保留堆栈内存的行为无论范围如何都是许多惊喜的来源。现代 C,又名 C99,具有旨在替代它的可变长度数组 (VLA)。但正如 Bo 所说,永远不要使用这样的东西在堆栈上只创建一个变量。这真的没有意义。
  • 我认为我没有正确编写上述测试代码。感谢您使用测试代码和有关 alloca 的附加信息解决问题。在我看来,我的工作组线程应用程序(不是上面的测试代码)的问题涉及分配和内存栅栏。我会尽快发布更好的牙签测试代码。

标签: c function-pointers alloca


【解决方案1】:

改变这一行:

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

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

因为queue[0]已经是一个指针;您不需要获取它的地址。 blah 内部也有同样的问题。你的printf 不会崩溃,但它会打印出指针的地址,而不是指针的值,这可能不是你想要的。

【讨论】:

  • 非常感谢!你是绝对正确的。那是当场的。 :-)
  • 如果您希望编译器为您发现此类问题,请取出所有强制转换并为“队列”提供正确的类型,而不是 void *[]。
【解决方案2】:

也许您还想传递参数“v”?

t->f = blah; // BAD

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

【讨论】:

    猜你喜欢
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多