按值传递va_list时访问冲突

Access violation when passing a va_list by value

本文关键字:访问冲突 list va 按值传递      更新时间:2023-10-16
当Microsoft Visual C++ 2005

按值将 va_list 参数从一个成员函数传递到另一个成员函数时,我收到访问冲突错误(使用 Visual 2005(。如果我通过引用传递它,一切都按预期工作,但va_list不应该通过引用传递,是吗?

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

<stdarg.h>中:

typedef char * va_list

所以A().getformatted( "foo%s", "bar" )由于字符串文字衰减到 C 兼容性而char *而调用A::getformatted( char const * a_format, va_list /*&*/ a_args)

如果逐步执行,是否按预期顺序调用两个函数?

显示的两个函数具有相似的签名,因此首先检查是确保调用正确发生。这一点尤其重要,因为va_list通常是char *的typedef,所以getformatted("foo%s", "bar")很可能在不先调用getformatted(const char *, ...)的情况下被调用。

如果是这种情况,并且vsprintf在任何时候都使用va_next,则行为将是未定义的。一些编译器将va_函数作为简单的宏处理,而其他编译器则具有重要的函数。

通常为了解决这个问题,带有va_list的函数将以v(vsprintf等人(为前缀,以消除任何潜在的歧义。

在最好的情况下,由于您使用的是C++,因此通常最好使用std::stringstreamboost::format。两者都会给你类型安全,并防止大多数这样的情况,而后者保留了printf的大部分语法。