2012-03-25 6 views
0

に別のメソッドに引数の変数num個を渡すコードとそれが動作:私は(例えば、目的のために簡略化)以下の持っているクラス

void log(const string type, const string msg, va_list argp) 
{ 
    fprintf(stdout, "[%s] ", type.c_str()); 
    vfprintf(stdout, msg.c_str(), argp); 
} 

void log_err(const string msg, ...) 
{ 
    va_list argp; 

    va_start(argp, msg); 
    log("ERROR", msg, argp); 
    va_end(argp); 
} 

私はこの方法でそれを使用します。

log_err("test: %d", 5); 
私はクラスにこれを移動したい場合

しかし:

class Logger { 
public: 
    Logger() { 
     // 
    }; 
    void generic(const string type, const string msg, va_list argp) { 
     fprintf(stdout, "[%s] ", type.c_str()); 
     vfprintf(stdout, msg.c_str(), argp); 
    }; 
    void error(const string msg, ...) { 
     va_list argp; 

     va_start(argp, msg); 
     this->generic("ERROR", msg, argp); 
     va_end(argp); 
    }; 
}; 

それから私は、セグメンテーションフォールトを得ました。マクロのようなトリッキーなことはクラススコープ内ではうまくいかないことが分かっていますが、その理由を知りたいのです。

アドバイスありがとうございます!

EDIT

使用例:

Logger logger; 
logger.error("test", 5); 

完全なソース:私は、元の使用中に、私はプライベートファイルディスクリプタを持っているので、これらのメソッドは、静的したくない

#include <string> 
#include <cstdlib> 
#include <cstdarg> 

using namespace std; 

void log(const string type, const string msg, va_list argp) 
{ 
    fprintf(stdout, "[%s] ", type.c_str()); 
    vfprintf(stdout, msg.c_str(), argp); 
} 

void log_err(const string msg, ...) 
{ 
    va_list argp; 

    va_start(argp, msg); 
    log("ERROR", msg, argp); 
    va_end(argp); 
} 

class Logger { 
    public: 
     Logger() { 
      // 
     }; 
     void generic(const string type, const string msg, va_list argp) { 
      fprintf(stdout, "[%s] ", type.c_str()); 
      vfprintf(stdout, msg.c_str(), argp); 
     }; 
     void error(const string msg, ...) { 
      va_list argp; 

      va_start(argp, msg); 
      this->generic("ERROR", msg, argp); 
      va_end(argp); 
     }; 
}; 

int main() 
{ 
    //log_err("test: %s\n", "str"); 

    Logger logger; 
    logger.error("test %s", 5); 

    return 0; 
} 

私はログメッセージを書いています。

+2

はまだ可変長引数テンプレートを得ましたか。 – sehe

+0

貼り付けたコードは上手く見えます。セグメンテーションフォルトはどこで発生しますか? 'エラー'の呼び出しはどうなるでしょうか? (そして、 'this->'を取り除く必要はありません) –

+0

実際に 'error()'をどう呼びますか?クラスとvarargsに関する '面倒なこと'は、可変引数リストに非PODオブジェクトを渡すことができないということです。 –

答えて

3

バグは、この行である:

 logger.error("test %s", 5); 

%s書式指定子は、Cスタイルの文字列です。 5はCスタイルの文字列ではありません。用途:

 logger.error("test %s", "5"); 

か:

 logger.error("test %d", 5); 
+0

うわー!出来た!私はそのような明白な事の上に落ちた、デイビッドに感謝する! –

+0

@SebastianSito:GCCを使用している場合は、 'printf()'形式の書式文字列を使用して関数をマークし、コンパイラにこのような問題について警告してもらうことができます。 '__attribute__((format(printf、2、3)))')のようなものがトリックをします(私は思う)。詳細はhttp://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.htmlを参照してください。 –

0

あなたはその道の99%です。

void generic(const string type, const string msg, va_list argp) 

void generic(const string type, const string msg, va_list & argp) 

には変更

EDIT(参照せずに行われている)あなたがリストをコピーすることはできませんようだ::私は上記の投稿は間違っています。最初のパスは、私が提供したものがフォールトされていると仮定し、参照なしではテストしませんでした。私は参照を削除し、すべてがうまく印刷されました。

未来の人のために残しました。

+0

上記の例はあなたのために働いていると言っていますか?コンパイルフラグと共にコードを貼り付けることはできますか? –

関連する問題