【发布时间】:2010-09-29 18:31:31
【问题描述】:
我有一个由一堆动态加载的模块组成的项目。最初,一切都是用 MSVC 2003 构建的,但最近我一直在努力让它与 GCC 一起工作。一切都很顺利,除了一个问题。对于 64 位代码,GCC 和 MSVC 不同意 va_list 是什么。对于 32 位,一切似乎都很好。 64 位不匹配导致的问题是,使用一个编译器构建的模块有一个带有 va_list 参数的公共函数,并且该函数是从另一个编译器构建的模块调用的。
除了第 7.15 节变量参数<stdarg.h>,第 3 段之外,规范没有说明 va_list 是什么:
声明的类型是
va_list这是一个对象类型,适合保存宏
va_start、va_arg、va_end和va_copy。
那段只是意味着这都是依赖于编译器的东西 - 那么,有没有办法让这两个编译器就 64 位 va_list 的内容达成一致?为了对我的系统影响最小,最好让 GCC 与 MSVC va_list 匹配,但我会采取任何我能得到的解决方案。
感谢您的帮助!
编辑:
我进行了一些 32 位测试,但我也遇到了问题,这让我感到惊讶,因为据说任何 32 位英特尔平台之间没有 ABI 差异。我使用的 MSVC 代码库将所有可变参数函数宏定义为:
typedef char *va_list;
#define intsizeof(n) ((sizeof(n) + sizeof(int) - 1) &~(sizeof(int) - 1))
#define va_start(ap, v) (ap = (va_list)&(v) + intsizeof(v))
#define va_arg(ap, t) (*(t *) ((ap += intsizeof(t)) - intsizeof(t)))
#define va_end(ap) (ap = (va_list)0)
我已经从实际项目中进行了一些简化,但这是我用于测试的代码。使用 GCC,这段代码肯定没有正确地得到我的论点。也许这只是一个错误,正如 Zack 在下面建议的那样?
再次编辑:
我得到以下 32 位测试应用程序的工作结果:-O0、-O0 和 -O2,但不是 -O3、-Os 和 -Oz:
typedef char *va_list;
#define intsizeof(n) ((sizeof(n) + sizeof(int) - 1) &~(sizeof(int) - 1))
#define va_start(ap, v) (ap = (va_list)&(v) + intsizeof(v))
#define va_arg(ap, t) (*(t *) ((ap += intsizeof(t)) - intsizeof(t)))
#define va_end(ap) (ap = (va_list)0)
int printf(const char *format, ...);
int f(int n, ...)
{
int r = 0;
va_list ap;
va_start(ap, n);
while (n--)
r = va_arg(ap, int);
va_end(ap);
return r;
}
int main(int argc, char **argv)
{
int r;
r = f(1, 1, 2, 3, 4, 5);
printf("%x\n", r);
r = f(2, 1, 2, 3, 4, 5);
printf("%x\n", r);
r = f(3, 1, 2, 3, 4, 5);
printf("%x\n", r);
r = f(4, 1, 2, 3, 4, 5);
printf("%x\n", r);
r = f(5, 1, 2, 3, 4, 5);
printf("%x\n", r);
return 0;
}
【问题讨论】:
-
呃。您将 MSVC 的
<stdarg.h>中的va_*定义复制到一个文件中,然后用 GCC 编译该文件,是这样吗?因为那绝对行不通,并且不会告诉您任何有用的信息。您绝对必须使用 GCC 的<stdarg.h>来定义使用 GCC(以及用于 MSVC 的 MSVC)编译的可变参数函数,否则您的代码将被错误编译。 -
这个测试你需要做的是将
f移动到它自己的文件中,将va_*的所有手定义替换为#include <stdarg.h>,在main上面放上“extern int f(int n, ...);”那个文件,用 GCC 编译一个,用 MSVC 编译另一个,然后链接这两个目标文件。那应该在 x32 或 x64 上在任一方向(MSVC 调用 GCC 或 GCC 调用 MSVC)上工作。跨度> -
是的,当关闭内联或将其放入单独的编译单元时,它工作得很好。无论如何,这是与不匹配的 va_list 类型完全不同的问题,正如您所说,这是编译器的错误。
标签: c gcc visual-studio-2003 variadic-functions