这似乎是clang中与空终止的变量参数列表有关的错误。
由于别名后面的参数为0,所以预期的行为是va_arg()在第一次迭代时将返回0。
完整代码如下。在main()中,删除“ void * map = 0;”或调用foo()会使错误消失。
#include <stdio.h>
#include <stdarg.h>
/*
clang --version:
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
*/
void *foo(char *a, char *b, char *c, ...) {
return 0;
}
void *bar(char *a, char *b, char *c, char *d, char *e, char *f, char *alias, ...) {
char *arg;
va_list ap;
va_start(ap, alias);
printf("alias = %s\n", alias);
while((arg = va_arg(ap, char *))) {
printf("arg = %p\n", arg);
printf("BUG!\n");
return 0;
}
va_end(ap);
printf("NO BUG\n");
return 0;
}
int main() {
void *map = 0; // removing this statement hides bug
foo(0, 0, 0, 0);// removing this statement hides bug
bar("a", "b", "c", "d", "e", "f", "b", 0);
}
输出为:
alias = b
arg = 0x100000000
BUG!
答案 0 :(得分:4)
0
不是char*
;这是int
。因此,使用va_arg(ap, char*)
进行读取是未定义的行为。
当您指的是类型(char*)0
的空指针时,请提供参数char *
。 (或者,如果愿意,可以使用(char*)NULL
。)在评论中指出,常见的NULL
是不正确的,因为NULL
可能被#define
命名为0
。
(由于0
是int
,所以编译器不必担心参数的高四位字节。参数的低四位字节确实为0。但这是实现细节;我只是以解释的方式提及它。)