参数太少的 C 函数调用

标签 c argument-passing

我正在处理一些遗留的 C 代码。原始代码是在 90 年代中期编写的,针对那个时代的 Solaris 和 Sun 的 C 编译器。当前版本在 GCC 4 下编译(尽管有很多警告),它似乎可以工作,但我正在努力整理它——我想尽可能多地排除潜在的错误,因为我确定可能需要什么使它适应 64 位平台,以及它所针对的编译器以外的编译器。

我在这方面的主要事件之一是确保所有函数都有完整的原型(prototype)(许多函数没有),在这种情况下,我发现了一些调用函数(以前没有原型(prototype))的代码,参数更少比函数定义声明的要多。函数实现确实使用了缺失参数的值。

例子:

实现.c:

int foo(int one, int two) {
  if (two) {
      return one;
  } else {
      return one + 1;
  }
}

client1.c:

extern foo();
int bar() {
  /* only one argument(!): */
  return foo(42);
}

client2.c:

extern int foo();
int (*foop)() = foo;
int baz() {
  /* calls the same function as does bar(), but with two arguments: */
  return (*foop)(17, 23);
}

问题:是否定义了缺少参数的函数调用的结果?如果是这样,该函数将为未指定的参数接收什么值?否则,ca 的 Sun C 编译器会不会。 1996(对于 Solaris,而不是 VMS)已经展示了一种可预测的特定于实现的行为,我可以通过向受影响的调用添加特定的参数值来模拟这种行为?

最佳答案

编辑:我找到了一个堆栈线程 C function with no parameters behavior 给出了非常简洁、具体、准确的答案。 PMG 在答案末尾的评论是关于 UB 的。以下是我最初的想法,我认为它们是相同的,并解释了为什么行为是 UB..

Questions: is the result of a function call with missing arguments defined?

我会说不......原因是我认为该函数将像它具有第二个参数一样运行,但如下所述,第二个参数可能只是垃圾。

If so, what value will the function receive for the unspecified argument?

我认为收到的值是未定义的。这就是您可以拥有 UB 的原因。

我知道有两种通用的参数传递方式...(维基百科在 calling conventions 上有一个很好的页面)

  1. 通过注册。即,平台的 ABI(应用程序二进制接口(interface))会说例如寄存器 x 和 y 用于传递参数,以及以上通过堆栈传递的任何其他...
  2. 一切都通过堆栈传递...

因此,当你给一个模块一个函数的定义时,“...未指定(但不是可变的)参数数量......”(extern def),它不会放置与你给它一样多的参数(在这种情况下 1) 在实际函数将查找以获取参数值的寄存器或堆栈位置中。因此,遗漏的第二个参数的第二个区域基本上包含随机垃圾。

编辑:基于我发现的另一个堆栈线程,我将上面的内容修改为 extern 声明了一个没有参数的函数到声明了一个具有“未指定(但不是可变的)参数数量”的函数。

当程序跳转到函数时,该函数假设参数传递机制已被正确遵守,因此要么查看寄存器或堆栈并使用它找到的任何值...假设它们是正确的。

Otherwise, would the Sun C compiler of ca. 1996 (for Solaris, not VMS) have exhibited a >> predictable implementation-specific behavior

您必须检查您的编译器文档。我对此表示怀疑...外部定义是否会被完全信任,因此我怀疑寄存器或堆栈是否会根据参数传递机制正确初始化...

关于参数太少的 C 函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17604189/

相关文章:

c - 如何坚持 C 编译器将局部变量放在堆栈上,而不是寄存器中

c - 内存搜索器功能中毫无根据的段错误

c++函数(带主体)作为参数

c - 皮格马利翁变换 : using "#define DLL" as replacement for "extern "C"__declspec(dllexport)"

c - 如何在C中不使用分号打印 "Hello"?

c - 使用 fscanf 读取复杂格式字符串

c - C 中函数不返回任何值

php - 将安全参数传递给功能还是让功能检查?

c# - 如何P/Invoke "__arglist"函数?

使用下拉列表运行的 Javascript 函数