遇到一个问题,在调用函数时出现错误。
有两个函数声明:
test.cpp
#include <stdarg.h>
#include <syslog.h>
void funcA( const char* format, ...); // No.1 func
void funcA( const char* format, va_list args_list); // No.2 func
int main()
{
int a = 2;
const char* str = "Hello";
char buf[10];
strcpy(buf, "test");
funcA("Call funcA: %d.", a); // Call the No.1 func
funcA("Call funcA: %s.", str); // Call the No.1 func
funcA("Call funcA: %s.", buf); // Call the No.2 func in mips-linux toolchain.
return 0;
}
void funcA( const char* format, ...)
{
va_list args_list;
va_start(args_list, format);
funcA(format, args_list);
va_end(args_list);
}
void funcA( const char* format, va_list args_list)
{
vsyslog(args_list);
}
编译上面的test.cpp文件,使用arm-linux toolchain就没有问题,都会调用到No.1函数。
但当使用mips-linux toolchain时,第三个就会调用到No.2函数,这种情况仅发生在format后面只有一个参数,且是char*变量时。
然后在调用到vsyslog这个系统函数时,程序就会卡死。
编译器在根据参数列表选择要调用的函数时,第一个参数两个函数都匹配,而第二个的话,char*就匹配到了va_list,优先于省略参数。
后面没有参数了,就选择了No.2函数进行调用。而从设计角度讲,不应该出现这样的两个函数 原型同时开发给外部,本就容易引起误解。
那为什么会如此匹配呢?
打开GCC工程的源码,来寻找一下va_list的定义。
会发现,这个类型的定义虽然由头文件stdarg.h提供,是C标准,但实际定义却是根据编译器、操作系统和ABI所决定的。在不同平台下,使用的定义也会不同。可能是个结构体,或者是个指针,或则是编译器内部实现的黑科技(black magic)。
1,#include <stdarg.h>
在gcc的工程里,有多个此同名文件。选取的是\gcc\ginclude\stdarg.h
2,在里面找到定义:
typedef __builtin_va_list __gnuc_va_list;
typedef __gnuc_va_list va_list;
3, 下载gcc的源码,在里面找到文件:gcc\

文章讨论了一个在MIPS架构下使用mips-linux工具链编译时遇到的问题,当调用funcA函数且参数为char*时,编译器错误地选择了第二个函数声明。问题归因于va_list在不同架构下的定义差异,以及编译器如何根据参数类型选择合适的函数。在MIPS中,va_list可能被定义为void*,导致了函数重载的混淆。而在ARM架构中,va_list有明确的结构体定义。
最低0.47元/天 解锁文章
716

被折叠的 条评论
为什么被折叠?



