2005-02-09 (Wed)
_ [C] エラー出力用マクロで可変長引数を使わずに__FILE__や__LINE__を埋め込む
Subversionのコードを読んでいて、GCC拡張やC99の可変長引数マクロを使わずに、 エラー出力用マクロで__FILE__や__LINE__を埋め込む方法を発見。
まず、次のようにエラー出力用の関数を用意しておく。
error.c:
#include <stdio.h>
#include <stdarg.h>
static const char *error_file = NULL;
static int error_line = -1;
void
my_error_locate(const char *file, int line)
{
error_file = file;
error_line = line;
}
void
my_error(const char *fmt, ...)
{
va_list ap;
fprintf(stderr, "%s:%d: ", error_file, error_line);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
}
そして、おもむろに次のようなマクロを定義。
error.h:
void my_error_locate(const char *file, int line); void my_error(const char *fmt, ...); #define error (my_error_locate(__FILE__, __LINE__), my_error)
あとは、このマクロをprintfのように使えばよい。
error_test.c:
#include <stdio.h>
#include "error.h"
int
main()
{
error("error - %d", 12345);
return 0;
}
コンパイル時に-ansi -pendanticを付けても文句を言われない。
$ gcc -ansi -pedantic -Wall error.c error_test.c -o error_test
実行すると、当然ちゃんとファイル名と行番号が出る。
$ ./error_test error_test.c:7: error - 12345
念のため動作原理を説明すると、
error("error - %d", 12345);
は展開されると、
(my_error_locate("error_test.c", 7), my_error)("error - %d", 12345);
のようになる。
my_error_locate()はstaticな変数にファイル名と行番号を格納する。
問題はその後だ。
カンマ演算子は左から右に評価されて、最後に評価された式の値が全体の値となる。
したがって、(..., my_error)の値はmy_errorの値、すなわち、
my_error()を指す関数ポインタになる。
その後で括弧が続いているということは・・・
そう、関数ポインタを経由したmy_error()の呼び出しになっているのだ。
#define error (*(my_error_locate(__FILE__, __LINE__), my_error))
と書いた方がわかりやすいかもしれない。
で、my_error()の中では、my_error_locate()が値をセットしたstaticな
変数を参照しているので、ファイル名と行番号をちゃんと表示できるというわけ。
よくできてますよね。
ちなみに、スレッドセーフじゃないんじゃ・・・というのが誰もが考えるところ だろうが、Subversionのコードには以下のようなコメントが書いてあった。
void
svn_error__locate (const char *file, long line)
{
/* XXX TODO: Lock mutex here */
error_file = file;
error_line = line;
}
[TrackBack URL: http://shugo.net/jit/tb.rb/20050209]
本日のリンク元
- http://q.hatena.ne.jp/1151935835 ×559
- http://gref.iblogs.com/ ×12
- http://here.iblogs.com/ ×12
- http://lostot.iblogs.com/ ×12
- http://mixi.jp/view_diary.pl?id=17795224&owner_id=... ×11
- http://tils.iblogs.com/ ×11
- http://gledis.iblogs.com/ ×11
- http://b.hatena.ne.jp/keisukefukuda/c/?mode=detail... ×6
- http://blogohost.com/andrianlee/ ×6
- http://andria.10e.net/ ×6
- http://ogawa.s18.xrea.com/tdiary/ ×6
- http://available.10e.net/ ×6
- http://b.hatena.ne.jp/add?mode=confirm&title=Journ... ×6
- http://b.hatena.ne.jp/tnakatani/c言語/?mode=detail&o... ×6
- http://ogawa.s18.xrea.com/tdiary/20050216.html ×6
- http://shachi6400.ika.hitachi-sk.co.jp/develop/kno... ×5
- http://clip.livedoor.com/page/191873/Journal InTim... ×4
- http://arika.org/diary/20041004 ×4
- http://d.hatena.ne.jp/oskimura/searchdiary?word=マク... ×4
- http://search.live.com/results.aspx?q=error ×4
- http://search.live.com/results.aspx?q=error&mrt=en... ×4
- http://rapislazuli.dyndns.org/~nimori/tdiary/?date... ×4
- http://b.hatena.ne.jp/kimata24/ ×3
- http://reader.livedoor.com/reader/ ×3
- http://b.hatena.ne.jp/keisukefukuda/c/ ×3
- http://sbs.mobile.yahoo.co.jp/union/search?fr=m_to... ×3
- http://www.fastriver.net/~ryo/pukiwiki.php?日記 ×3
- http://sbs.mobile.yahoo.co.jp/union/search?p=引数エラー... ×3
- http://sbs.mobile.yahoo.co.jp/union/search?fr=m_to... ×3
- http://d.hatena.ne.jp/oskimura/searchdiary?word=デバ... ×2
- http://search.live.com/results.aspx?q=可変長マクロ&form=... ×2
- http://b.hatena.ne.jp/bingo_nakanishi/ ×2
- http://b.hatena.ne.jp/tnakatani/c言語/?mode=detail ×2
- http://b.hatena.ne.jp/keyword/Char ×2
- http://www.fastriver.net/~ryo/pukiwiki.php?日記/2007... ×2
- http://clip.livedoor.com/clips/inuneco ×2
- http://b.hatena.ne.jp/ima/?word=可変長&cname= ×2
- http://search.hatena.ne.jp/search?word=__LINE__ ×2
- http://rapislazuli.dyndns.org/~nimori/tdiary/20050... ×2
- http://blog.drecom.jp/FFF/archive/18 ×2
- http://sbs.mobile.yahoo.co.jp/union/search?p=マクロ ×2
- http://d.hatena.ne.jp/oskimura/20070802/1186057604... ×1
- http://search.live.com/results.aspx?q=可変長引数 C99&fo... ×1
- http://search.live.com/spresults.aspx?q=エラー マクロ ×1
- http://search.live.com/results.aspx?q=gcc __LINE__... ×1
- http://search.live.com/spresults.aspx?q=Live searc... ×1
- http://looseend.ddo.jp/blog/9 ×1
- http://pub.cozmixng.org/~the-rwiki/rw-cgi.rb?cmd=v... ×1
- http://sbs.mobile.yahoo.co.jp/union/search?fr=m_to... ×1
- http://search.www.infoseek.co.jp/OTitles?col=OW&qt... ×1
- http://rapislazuli.dyndns.org/~nimori/tdiary/?date... ×1
- http://imp.sdl.hitachi.co.jp/horde/imp/message.php... ×1
- http://search.live.com/spresults.aspx?q=可変長引数の関数ポイ... ×1
- http://search.live.com/results.aspx?q=_imp_fprintf... ×1
- http://rapislazuli.dyndns.org/~nimori/tdiary/ ×1
- http://clip.livedoor.com/clips/inuneco/tag/c ×1
- http://search.live.com/results.aspx?q=JITデバック&mkt=... ×1
- http://search.live.com/results.aspx?mkt=ja-jp&FORM... ×1
- http://s.luna.tv/search.aspx?client=lunascape-etc&... ×1
- http://search.www.infoseek.co.jp/Web?qt=C99 マクロ 可変... ×1
- http://sbs.mobile.yahoo.co.jp/union/search?p=引数 ×1
- http://www.rubyist.net/~matz/20041104.html ×1
- http://search.live.com/spresults.aspx?q=Mail エラー S... ×1
- http://d.hatena.ne.jp/oskimura/searchdiary?word=JI... ×1
- http://ogawa.s18.xrea.com/tdiary/200502.html ×1
- http://search.live.com/results.aspx?srch=106&FORM=... ×1
- http://search.live.com/results.aspx?q=define マクロ 可... ×1
- http://ogawa.s18.xrea.com/tdiary/0216.html ×1
- http://ysearch.luna.tv/search.aspx?p=my_error_loca... ×1
- http://d.hatena.ne.jp/oskimura/searchdiary?word=メモ... ×1
- http://sbs.mobile.yahoo.co.jp/union/search?p=引数エラー... ×1
- http://search.live.com/previewx.aspx?q=_FILE_ マクロ&... ×1
- http://search.live.com/results.aspx?q=__FILE__ マクロ... ×1
- http://clip.livedoor.com/ ×1
- http://search.live.com/spresults.aspx?q=JITデバック ×1
- http://sbs.mobile.yahoo.co.jp/union/search?fr=m_to... ×1
- http://search.live.com/results.aspx?mkt=ja-jp&FORM... ×1
- http://search.live.com/spresults.aspx?q=C マクロ 可変 ×1
- http://rapislazuli.dyndns.org/~nimori/tdiary/20040... ×1
- http://clip.livedoor.com/recent/ ×1
- http://rapislazuli.dyndns.org/~nimori/tdiary/?date... ×1
- http://search.live.com/results.aspx?q=__LINE__ __F... ×1
- http://search.www.infoseek.co.jp/OTitles?col=OW&qt... ×1
- http://search.live.com/spresults.aspx?q=マクロのエラー&fo... ×1
- http://search.www.infoseek.co.jp/OTitles?col=OW&qt... ×1
- http://tach.arege.net/d/200408.html ×1
- http://search.live.com/results.aspx?q=gcc マクロ 可変長引... ×1
- http://bloger.x0.com/result/c言語/c言語 コンパイル ×1
- http://ogawa.s18.xrea.com/tdiary/20060110.html ×1
- http://search.live.com/results.aspx?q=_FILE_ _LINE... ×1
- http://www.tumblr.com/dashboard ×1
- http://search.live.com/results.aspx?q=__LINE__ __F... ×1
- http://www.rubyist.net/~matz/20070410.html ×1
- http://search.live.com/results.aspx?q=_lock_file s... ×1
- http://tokuhirom.dnsalias.org/~tokuhirom/inamode2/... ×1
- http://d.hatena.ne.jp/oskimura/20070802 ×1
- http://www.itmedia.co.jp ×1
- http://search.live.com/results.aspx?q=gcc __LINE__... ×1
- http://search.live.com/spresults.aspx?q= Windows J... ×1
- http://mgw.hatena.ne.jp/?http://shugo.net/jit/2005... ×1

この方法でソース中に埋め込んだ全デバックを、一括で無効にしたい場合にいい方法はありますか?