简体   繁体   English

按值传递va_list时访问冲突

[英]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. 我通过值将va_list参数从一个成员函数传递到另一个成员函数时出现访问冲突错误(使用Microsoft Visual C ++ 2005)。 If I pass it by reference everything works as expected but va_list isn't supposed to be passed by reference, is it? 如果我通过引用传递它一切都按预期工作但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;
}

In <stdarg.h> : <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. 所以A().getformatted( "foo%s", "bar" )调用A::getformatted( char const * a_format, va_list /*&*/ a_args)因为C字符串文字由于C兼容性而衰减为char *

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. 这一点特别重要,因为va_list通常是char *的typedef,所以getformatted("foo%s", "bar")可以很好地调用,而不getformatted(const char *, ...)调用getformatted(const char *, ...)

If that is the case, and vsprintf uses va_next at any point, the behavior will be undefined. 如果是这种情况,并且vsprintf在任何时候使用va_next ,则行为将是未定义的。 Some compilers handle the va_ functions as simple macros, while others have significant functions. 有些编译器将va_函数作为简单宏处理,而其他编译器则具有重要功能。

Typically to solve this, the function with va_list will be prefixed with a v ( vsprintf et al) to remove any potential ambiguity. 通常,为解决此问题,带有va_list的函数将以v vsprintfvsprintf等),以消除任何潜在的歧义。

In the best case, since you're using C++, a std::stringstream or boost::format are generally preferable. 在最好的情况下,由于您使用的是C ++,因此通常首选std::stringstreamboost::format Both will give you type safety and prevent most situations like this, while the latter retains most of printf 's syntax. 两者都会为您提供类型安全性并防止大多数类似情况,而后者保留了printf的大部分语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM