1

我正在使用 g++ 编写一个 64 位操作系统,并且我有一个可变参数函数,例如:

void DbgPrint(const char *fmt, ...);

它的行为与 printf 非常相似。这里的问题是 g++ 遵循 System V ABI,因此它传递 RDI、RSI、RDX、RCX、R8、R9 中的第一个参数,然后将剩余的(如果有的话)压入堆栈。

将旧的 stdarg.h 宏 va_start、va_arg 等与 cdecl 一起使用非常容易,因为 va_arg 只是获取堆栈中的下一个元素。但是现在这些宏在第 7 个参数之前根本不起作用。

唯一可能的解决方案是(恕我直言):

  • 强制 g++ 创建一个 cdecl 函数。这似乎是不可能的,因为__属性__ ((cdecl)) 被故意清晰地突出显示为忽略
  • 拥有一组新的宏,可以使用新的参数传递方式。

(我实际上正在开发 Win,所以我没有 glibc 标头来检查它们的实现)。

有人有解决方案吗?提前致谢。

4

1 回答 1

2

stdarg.h 不是 libc 的一部分,它是编译器本身的一部分。因此,如果您使用 g++,它应该有一个附带的 stdarg.h 来处理这个问题——它通常安装在 gcc 的私有包含目录中,在系统包含之前会自动搜索该目录。

如果您查看 gcc 的 stdarg.h,您会看到 va_ 宏都被定义为映射到编译器神奇地知道如何处理的 __builtin 函数:

typedef __builtin_va_list __gnuc_va_list;
typedef __gnuc_va_list va_list;

#define va_start(v,l)   __builtin_va_start(v,l)
#define va_end(v)   __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)

并且那些内置函数都理解目标 ABI 使用的调用约定。

于 2012-03-26T17:21:09.073 回答