首页 > 解决方案 > 与stdarg相关的clang错误?

问题描述

这似乎是与空终止变量参数列表相关的 clang 中的一个错误。

预期的行为是 va_arg() 将在第一次迭代时返回 0,因为别名后面的参数是 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!

标签: cclang

解决方案


0不是一个char*;这是一个int. 所以阅读它va_arg(ap, char*)是未定义的行为。

(char*)0当您的意思是类型为空的指针时,请提供参数char *。(或者(char*)NULL,如果您愿意。)正如 MM 在评论中指出的那样,常见的NULL不正确,因为NULL可能#defined 为0

(既然0是 an int,编译器就不关心高四字节了。参数的低四字节确实是0。但这是一个实现细节;我只是作为解释的方式提到它。)


推荐阅读