Baltram
Baltram

Reputation: 681

Access violation when passing a va_list by value

I'm getting an access violation error (using Microsoft Visual C++ 2005) when passing a va_list parameter from one member function to another by value. If I pass it by reference everything works as expected but va_list isn't supposed to be passed by reference, is it?

class A
{
public:
    char * getformatted( char const * a_format, ... )
    {
        va_list argp;
        va_start( argp, a_format );
        char * result = getformatted( a_format, argp );
        va_end( argp );
        return result;
    }
    char * getformatted( char const * a_format, va_list /*&*/ a_args )
    {
        static char buffer[ 256 ];
        int length = vsprintf( buffer, a_format, a_args );  // Access violation.
        return buffer;
    }
};

int main( int argc, char * argv[] )
{
    char * str = A().getformatted( "foo%s", "bar" );
    return 0;
}

Upvotes: 1

Views: 1033

Answers (2)

MSN
MSN

Reputation: 54634

In <stdarg.h>:

typedef char * va_list

so A().getformatted( "foo%s", "bar" ) is calling A::getformatted( char const * a_format, va_list /*&*/ a_args) due to a string literal decaying to char * due to C compatibility.

Upvotes: 2

ssube
ssube

Reputation: 48307

If you step through execution, are both functions being called in the expected order?

Both the functions shown have similar signatures, so the first check is to make sure the call is occurring properly. This is particularly important since va_list is typically a typedef to char *, so getformatted("foo%s", "bar") could very well be called without getformatted(const char *, ...) being called first.

If that is the case, and vsprintf uses va_next at any point, the behavior will be undefined. Some compilers handle the va_ functions as simple macros, while others have significant functions.

Typically to solve this, the function with va_list will be prefixed with a v (vsprintf et al) to remove any potential ambiguity.

In the best case, since you're using C++, a std::stringstream or boost::format are generally preferable. Both will give you type safety and prevent most situations like this, while the latter retains most of printf's syntax.

Upvotes: 1

Related Questions