標準出力とファイルと両方に書く関数を作ったとして、
この書き方は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 マクロは呼び出されない。
Man page of PRINTF
これらの関数は va_arg を呼び出すので、呼び出し後の ap の値は未定義である。
stdarg(3) を参照のこと。
昔は使いまわせたけど今は破壊されるようになってるので、このコードは★のところでセグメンテーション違反で落ちる可能性がある
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