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

标签 c++ visual-studio reference visual-studio-2003 variadic-functions

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

我得到:

Access violation reading location 0xcccccccc

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

最佳答案

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

关于c++ - 将引用作为命名参数传递给可变参数函数时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2853100/

相关文章:

C++ 使用 fstream

vector - 在 Rust 中拥有多个链表并在它们之间移动数据的正确方法是什么?

C++ 传递 STL 容器项作为引用

c++ - std::allocator 是否需要默认可构造?

c++ - 处理质量 Spring 系统之间碰撞的好方法

visual-studio - x64汇编指令“nop dword ptr [rax + rax]”有什么作用?

c# - LibUsbDotNet 调用 UsbDevice.AllDevices 时找不到设备

c# - 为什么需要在 C# 中使用 DispId 注释?

c++ - 正在初始化类型为 "int &"的引用(不是 const 限定的),其值是 "bool"类型的一些 hack?

c++ - 模板和函数指针