调用具有比预期更多参数的C函数是否安全?

时间:2014-04-09 18:40:42

标签: c

我正在维基百科上阅读有关cdecl通话约定的内容。由于参数以相反的顺序被压入堆栈,我相信使用比预期更多的参数调用C函数是安全的。

我是对的还是我错过了什么?

注意:我不是在谈论可变函数。

4 个答案:

答案 0 :(得分:6)

我刚刚快速浏览了ISO / IEC 9899(又名C99):没有任何关于在任何地方调用约定的信息,因此(正如评论中所建议的那样)你应该明确不做此。即使它可能在某个体系结构,某个操作系统和某个特定版本的某个编译器上工作,但绝对没有保证它只在仅这些参数的一个会发生变化。

答案 1 :(得分:5)

你犯了一个大错误的假设:所谓的C调用约定对于C来说不是契约性的。
虽然旧的C编译器被迫使用这样的调用约定(即使它不是最理想的),但是由于没有函数原型,现代编译器可以(并且被允许)使用更高效的被调用者清理调用约定,而不是旧的 - 风格和vararg功能。大多数编译器都有一个开关来选择使用的标准调用约定。

答案 2 :(得分:4)

不是!!!

此代码导致分段错误:

#include <stdio.h>

#define stdcall __attribute__((stdcall))

stdcall void func(int param1, int param2)
{
    printf("%d, %d\n", param1, param2);
}

int main()
{
    void(*f)(int, int, int) = func;
    f(66, 67, 666);
    f(1, 2, 3);

    return 0;
}

这只是对其他人指出的关于召集惯例的阐述。我相信POC有助于说明问题。

答案 3 :(得分:1)

是的,它是安全的,部分原因是你给出的(params按相反顺序推),部分原因是调用约定。

C致电会议
C调用约定是调用者清理参数 (另一种方法是Callee清理)。

因为调用者知道它推了多少个参数,所以无论Callee使用或预期有多少参数,它都会知道要正确清理多少参数。


按相反顺序推送args
当参数以相反的顺序被压入堆栈时,第一个参数将被推送到最后。无论推送了多少个参数,Callee总是知道在堆栈顶部找到#1的参数。 (以及param#2,#3等)。

如果堆栈约定被反转,则param 1将首先放在堆栈上,并且可能被埋入&#34;通过任意数量的后续参数; Callee不知道要看堆栈的距离。