【问题标题】:In C, using a pointer to a struct to call a function pointed to inside the struct leads to seg fault在 C 中,使用指向结构的指针来调用指向结构内部的函数会导致段错误
【发布时间】:2014-07-19 16:16:03
【问题描述】:

我对函数指针没有经验,但我认为这是我应该知道的,所以我使用了一个简单的程序。我越来越多地在内核对象领域工作,其中结构和函数指针相当普遍。

这会导致段错误:

int nada(int input){
    printf("value = %d", input);
}

typedef struct foo{
    void (*funcptr)(int);
}foo;

main()
{
    foo* FOO;
    FOO->funcptr = nada;

    FOO->funcptr(5);
}

但是有一个这样的 main 代替:

main()
{
    foo FOO;
    FOO.funcptr = nada;

    FOO.funcptr(5);
}

不会导致段错误。

另外,我收到一个关于函数指针分配的警告:

main.c:16:17: 警告:来自不兼容指针类型的赋值 [默认启用] FOO.funcptr = nada;

有人解释一下吗?

【问题讨论】:

  • foo* FOO; :它不指向一个对象(foo )。 void (*funcptr)(int); 类型也不同。
  • 以什么方式使用 typedef 而不是简单地声明变量 struct foo FOO 会使任何事情更清楚? typedef 非常适合定义复杂的函数指针类型,但对于简单的结构,它们只是混淆了。
  • @WilliamPursell 我只是对一个更复杂且更常用的结构类型进行建模。
  • @aruisdante:我的观点是,通过编写 'struct foo' 显式声明变量类型要清楚得多。打字的最小节省并不能证明额外的晦涩是合理的。这通常是错误的来源,(例如,当 typedef 掩盖了指针类型时)几乎没有什么好处。

标签: c function pointers struct function-pointers


【解决方案1】:

当你有

foo* FOO;
FOO->funcptr = nada;

FOO 是指针,您应该在访问它之前为其分配内存。否则,您将访问可能会导致崩溃的随机内存。

所以更新代码

foo* FOO = malloc(sizeof(*FOO));
FOO->funcptr = nada;

并释放曾经使用过的内存。


警告

main.c:16:17: 警告:来自不兼容指针类型的赋值 [默认启用] FOO.funcptr = nada;

您已将nada 定义为返回int 的函数。但是您指向函数的指针没有返回任何不匹配的内容(具有void 返回类型),因此会发出警告。

【讨论】:

  • 谢谢!现在完全有道理了。
  • 有点吹毛求疵:访问未初始化的变量会产生未定义的行为。编译器可能(并且将)检测到这一点,并可能以任何它想要的方式利用它。生成导致程序崩溃的代码是一个完全有效的结果,但编译器也可以将其转换为对rm -rf / 的调用。
  • @datenwolf,这就是为什么我说可能会导致崩溃
  • @Rohan:好吧,您还写了“随机记忆”,这不是未定义行为的含义。编译器也可以决定始终从地址0xdeadbeef 读取未初始化的指针位置,这绝对不是随机的。还要记住,未初始化的指针与空指针不同。从空指针读取也会调用未定义的行为,但语义不同。 –– 我在这里不是语言律师,但是编写编译器的人会这样做,如果您的程序调用未定义的行为,这可能会变成一个问题。
【解决方案2】:

在你原来的行中,这个:

foo* FOO;

不创建foo,它创建一个指向foo 的指针,该指针当前不指向任何东西。然后你尝试访问不存在的foo

FOO->funcptr = nada;

导致段错误,因为该指针没有指向任何地方(这在技术上是未定义的,它可以做任何事情,但通常会出现段错误)。

在你的另一个例子中,这个:

foo FOO;

实际上创建了一个foo 实例,因此访问/分配其成员是合法的。您需要使用foo* FOO = malloc(sizeof(foo)) 创建一个新的foo,该foo 直接分配一个指针(记住要释放!),或者将指针分配给现有的foo 实例。

【讨论】:

  • 谢谢!现在完全有道理了。
【解决方案3】:

试试这个..不使用 malloc()

#include <stdio.h>

int nada(int input){
    printf("value = %d", input);
}

typedef struct foo{
    int (*funcptr)(int input);
} foo;

main()
{
    foo Foo;
    Foo.funcptr = nada;
    Foo.funcptr(5);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-29
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    相关资源
    最近更新 更多