代码之家  ›  专栏  ›  技术社区  ›  Michael Mrozek

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

  •  5
  • Michael Mrozek  · 技术社区  · 15 年前

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

    我得到:

    访问冲突读取位置0xCCCCCC

    printf() 线—— va_arg() 返回0xCCCCCC。最后我发现它是第一个参数,它是一个引用,如果我把它变成一个普通的char*一切都很好。它似乎与类型无关;作为引用会导致它在运行时失败。这是VS2003的一个已知问题,还是存在某种法律行为?在GCC中不会发生这种情况;我还没有用新的视觉工作室来测试这种行为是否会消失。

    1 回复  |  直到 15 年前
        1
  •  2
  •   Patrick    15 年前

    VS2005也崩溃了。

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

    我看不到获取堆栈变量地址的方法(实际包含正在传递的“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);
           }
        }
    }