c - C 中的函数指针及其行为

标签 c gcc segmentation-fault

我正在试验 c 和函数指针。以下代码在 gcc 作为编译器时运行良好。

typedef int( * one_var_func)(int);

int Multiply(int x, int y) {
  return x * y;
}

one_var_func curry(int( * f)(int, int), int x) {
  int curried_f(int y) {
    return f(x, y);
  }
  return (curried_f);
}

int apply(int( * f)(int), int x) {
  return f(x);
}

int main() {
  int( * p)(int, int);
  one_var_func q;
  int e;
  p = & Multiply;
  q = curry(p, 2);
  e = apply( * q, 10);
  printf("%d \n", e);
  return 1;
}

然而,当我进行这个小修改时;

int apply(int (*f)(int) ,int x){
  int a;
  a=f(x)
  return a;
}

程序抛出一个段错误。我不明白为什么以及如何。一个解释会非常好。

最佳答案

嵌套函数是标准 C 中不存在的 GCC 扩展,因此这个答案(如问题)是特定于 GCC 的。

C 中的嵌套函数不提供闭包。也就是说,嵌套函数只能访问外层函数的局部变量,直到外层函数返回。 GCC documentation关于这个主题有以下说法:

If you try to call the nested function through its address after the containing function exits, all hell breaks loose. If you try to call it after a containing scope level exits, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it’s not wise to take the risk. If, however, the nested function does not refer to anything that has gone out of scope, you should be safe.

您的代码的两个版本都违反了此规则,那么为什么只有一个版本会导致段错误?一个答案是,就像“未定义的行为”一样,“一切都乱套了”可以描述所有类型的行为,包括看似按预期工作。

更面向实现的答案是,从函数返回实际上不会立即删除其在堆栈上的内容 - 值只是保留在那里,直到另一个函数在需要堆栈空间时覆盖它们。引入新的局部变量会使函数需要更多堆栈空间,因此您的第二个函数会覆盖以前版本没有的堆栈内存。

关于c - C 中的函数指针及其行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47175099/

相关文章:

c++ - 为什么 COM DLL 导出应标记为 "PRIVATE"?

c - 尝试将一个结构体的字段复制到 c 中的另一个结构体?

c - 为什么 Linux 中的所有系统调用都使用 "call by reference"将参数传递给内核?

c++ - 帮助用 gcc/g++ 编译

c - 避免段错误

c++ - 覆盖 DirectX 结构的新建和删除

c - 如何使用getchar将ASCII码转换成对应的int?

c++ - 从已弃用的类继承

c++ - 尝试以特定长度将字符串从一个复制到另一个时出现段错误?

node.js - nodejs-0.4.2 启动时出现段错误(在 v 0.4.5 中修复)