5

我在 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);
    }
}

当我调用它时:

const char* one = "one";
foo(one, "two", "three", NULL);

我得到:

访问冲突读取位置 0xcccccccc

printf()线——va_arg()返回0xcccccccc。我终于发现它的第一个参数是破坏它的引用——如果我把它变成一个普通的 char* 一切都很好。类型是什么似乎并不重要。作为参考会导致它在运行时失败。这是VS2003的一个已知问题,还是有某种合法行为?它不会发生在 GCC 中。我尚未使用较新的 Visual Studio 进行测试以查看行为是否消失

4

1 回答 1

2

VS2005 也崩溃了。

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

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

  • 代替“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);
       }
    }
}
于 2010-05-18T08:31:14.863 回答