static void __warnx(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (lopt) vsyslog(LOG_WARNING, fmt, ap); if (eopt) vwarnx(fmt, ap); va_end(ap); } |
loptとeoptの両方が真の時、vwarnx(3)の出力が乱れるのだ。
vsyslog(3)とvwarnx(3) を入れ替えると、必ず後に呼ばれる方が乱れることから、v付きの関数が呼ばれる度にapが消費されるのではないかと考え、以下のようにそれぞれのv付き関数にapを新しく確保するようにしたらうまく行った。
static void __warnx(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (lopt) vsyslog(LOG_WARNING, fmt, ap); va_end(ap); va_start(ap, fmt); if (eopt) vwarnx(fmt, ap); va_end(ap); } |
このことはva_start(3)のマニュアルページには明記されていない。
va_copy(3)を使ってapを複製・保存(va_copy(aq, ap);)するという手もあるのかも知れないが、その際、マニュアルページにはva_copy(3)で複製されたaqはva_end(aq);で開放しなければならないと書いてあるが、複製元のapについては明記されていない(通常はva_start(3)で確保されたapは必ずva_end(3)で開放)。
深入りするのが面倒なので今回はこれでよしとする。
0 件のコメント:
コメントを投稿