2012-03-01 14 views
1

あるメンバ関数から別のメンバ関数に値でva_listパラメータを渡すと、アクセス違反エラー(Microsoft Visual C++ 2005を使用)が発生します。私がそれを渡すと、すべてが期待どおりに機能しますが、va_listは参照渡しされていないと思われます。値で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; 
} 

答えて

1

実行をステップ実行すると、両方の関数が予期された順序で呼び出されていますか?

表示されている機能には同じシグネチャがあるため、最初のチェックではコールが適切に行われていることを確認します。これは特に重要です。va_listがtypedefからchar *になるので、getformatted("foo%s", "bar")は最初にgetformatted(const char *, ...)と呼ばれることなく呼び出すことができます。

この場合、vsprintfはいつでもva_nextを使用しますが、動作は未定義です。コンパイラの中には、va_の機能を単純なマクロとして処理するものと、重要な機能を持つものがあります。

通常、これを解決するために、va_listの関数の先頭にはvvsprintfなど)という接頭辞が付けられ、潜在的なあいまいさが取り除かれます。

ベストケースでは、C++を使用しているため、一般にstd::stringstreamまたはboost::formatが好ましいです。両方とも型の安全性を提供し、このようなほとんどの状況を防ぎますが、後者はほとんどprintfの構文を保持します。 <stdarg.h>

2

typedef char * va_list 

のでA().getformatted("foo%s", "bar")が原因によるCとの互換性にchar *に減衰するリテラル文字列にA::getformatted(char const * a_format, va_list /*&*/ a_args)を呼んでいます。

関連する問題