将引用作为命名参数传递给可变参数函数时出现问题

Mic*_*zek 5 c++ visual-studio-2003 reference variadic-functions visual-studio

我在Visual Studio 2003中遇到以下问题:

void foo(const char*& str, ...) {
    va_list args;
    va_start(args, str);

    const char* foo;
    while((foo = va_arg(args, const char*)) != NULL) {
        printf("%s\n", foo);
    }
}
Run Code Online (Sandbox Code Playgroud)

我打电话的时候:

const char* one = "one";
foo(one, "two", "three", NULL);
Run Code Online (Sandbox Code Playgroud)

我明白了:

访问冲突读取位置0xcccccccc

printf()线- va_arg()返回0xcccccccc.我终于发现它的第一个参数是一个打破它的引用 - 如果我把它作为普通的char*一切都很好.这种类型似乎并不重要; 作为引用会导致它在运行时失败.这是VS2003的已知问题,还是某种方式存在合法行为?它不会发生在海湾合作委员会; 我还没有测试过更新的Visual Studios,看看这个行为是否会消失

Pat*_*ick 2

VS2005 也崩溃了。

问题是 va_start 使用给它的参数的地址,并且由于 str 是一个引用,因此它的地址是调用者定义的“one”变量的地址,而不是堆栈上的地址。

我看不到如何获取堆栈变量的地址(实际上包含正在传递的“一”的地址的参数),但有一些解决方法:

  • 使用“const char *str”或“const char **str”代替“const char * &str”
  • 将下一个参数也添加到“固定”参数列表中

此代码说明了第二种选择:

void foo(const char* &str, const char *arg1, ...) {
    if (arg1) {
       va_list args;
       va_start(args, arg1);
       printf ("%s\n", arg1);
       const char* foo;
       while((foo = va_arg(args, const char*)) != NULL) {
           printf("%s\n", foo);
       }
    }
}
Run Code Online (Sandbox Code Playgroud)