与stdarg相关的clang错误?

时间:2018-09-12 01:50:07

标签: c clang

这似乎是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!

1 个答案:

答案 0 :(得分:4)

0不是char*;这是int。因此,使用va_arg(ap, char*)进行读取是未定义的行为。

当您指的是类型(char*)0的空指针时,请提供参数char *。 (或者,如果愿意,可以使用(char*)NULL。)在评论中指出,常见的NULL是不正确的,因为NULL可能被#define命名为0

(由于0int,所以编译器不必担心参数的高四位字节。参数的低四位字节确实为0。但这是实现细节;我只是以解释的方式提及它。)