5

I'm having problems in Visual Studio 2003 with the following:

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

When I call it:

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

I get:

Access violation reading location 0xcccccccc

on the printf() line -- va_arg() returned 0xcccccccc. I finally discovered it's the first parameter being a reference that breaks it -- if I make it a normal char* everything is fine. It doesn't seem to matter what the type is; being a reference causes it to fail at runtime. Is this a known problem with VS2003, or is there some way in which that's legal behavior? It doesn't happen in GCC; I haven't tested with newer Visual Studios to see if the behavior goes away

Bertrand Marron
  • 21,501
  • 8
  • 58
  • 94
Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175

1 Answers1

2

VS2005 also crashes on it.

The problem is that va_start uses the address of the argument given to it, and since str is a reference, its address is the address of the "one" variable defined int the caller, not the address on the stack.

I see no way of getting the address of the stack-variable (the argument that actually contains the address of "one" that is being passed), but there are some work arounds:

  • Instead of "const char * &str", use "const char *str" or "const char **str"
  • Add the next argument also to the "fixed" argument list

This code illustrates the second alternative:

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);
       }
    }
}
Patrick
  • 23,217
  • 12
  • 67
  • 130
  • Oh, that's really obvious in retrospect; I guess glibc's implementation of `va_start` doesn't depend on the address of the final named argument, it figures out the start of the ... some other way – Michael Mrozek May 18 '10 at 14:07
  • 1
    Just found at http://www.velocityreviews.com/forums/t281115-va_start-and-references.html that using va_start on a reference is not allowed. Also see http://stackoverflow.com/questions/222195/are-there-gotchas-using-varargs-with-reference-parameters. – Patrick May 18 '10 at 14:30
  • Just searched for "va_arg reference C++", et voila. – Patrick May 18 '10 at 19:58