揮発性のメモ2

http://d.hatena.ne.jp/iww/

可変引数の関数で、va_listは使いまわせない

標準出力とファイルと両方に書く関数を作ったとして、

この書き方はNG

int log_printf( FILE *fp, char *f, ... )
{
    va_list v;

    va_start( v, f );

    vprintf( f, v ); // 標準出力
    vfprintf( fp, f, v ); // ファイル出力 ★

    va_end( v );
}

これらの関数では va_end マクロは呼び出されない。
これらの関数は va_arg を呼び出すので、呼び出し後の ap の値は未定義である。
stdarg(3) を参照のこと。

Man page of PRINTF

昔は使いまわせたけど今は破壊されるようになってるので、このコードは★のところでセグメンテーション違反で落ちる可能性がある

int log_printf( FILE *fp, char *f, ... )
{
    va_list v;
    char buf[1024];

    va_start( v, f );

    vsnprintf(buf,sizeof(buf), f,v); // バッファにいったん書き出す
    printf( "%s", buf ); // 標準出力
    fprintf( fp, "%s", buf ); // ファイル出力

    va_end( v );
}

使いまわさなければよいので、いったんバッファにでも書き出せばいい


どうしても使いまわしたいときは va_copy でコピーできるらしい
Man page of STDARG