Table of Contents
デバッグログファイルの文法は以下の通り:
>debugfile< :== { >debugmsg< } >debugmsg< :== >debughdr< '\n' >debugtext< >debughdr< :== '[' TIME ',' LEVEL ']' FILE ':' [FUNCTION] '(' LINE ')' >debugtext< :== { >debugline< } >debugline< :== TEXT '\n'
TEXTは改行文字を含まない文字列である。
LEVEL はメッセージのDEBUGレベルである(0から10の範囲の整数値)。
TIME はタイムスタンプである。
FILE はでバグメッセージが生成されたファイルの名前である。
FUNCTIONはデバッグメッセージが生成された関数である。
LINEはメッセージが生成されたデバッグ文の行番号である。
基本的に、それが意味するところは以下の通り:
デバッグログファイルはデバッグメッセージで構成される。
核でバッグメッセージはヘッダーとテキストから構成される。ヘッダーは改行によってテキストと 分離されている。
ヘッダーはタイムスタンプで始まり、括弧の中にデバッグレベルが続く。メッセージによって 生成されたファイル名、関数名、と行番号がそのあとに続く。ファイル名はコロンで終了し、 関数名は行番号を含む括弧で終了する。コンパイラに依存するが、関数名は無いかもしれない (これは、広く実装はされていない__FUNCTION__マクロによって生成される、dangit)。
メッセージテキストは0かそれ以上の行から構成され、おのおのは改行で終端する。
出力の例:
[1998/08/03 12:55:25, 1] nmbd.c:(659) Netbios nameserver version 1.9.19-prealpha started. Copyright Andrew Tridgell 1994-1997 [1998/08/03 12:55:25, 3] loadparm.c:(763) Initializing global parameters
上記の例において関数名はヘッダー行には表示されていないことに注意。これは、上記の例は SGI Indyによって生成され、SGIコンパイラは__FUNCTION__マクロをサポートしていないという 理由による。
DEBUG()マクロの使用は変わっていない。DEBUG()は2つのパラメーターをとる。 最初のものはメッセージレベルであり、2番目のものはDebug1()関数を呼び出すための 関数呼び出しの実体である。
これは混乱させる。
若干の手助けとなるかもしれない例は以下の通り。もしも
printf( "This is a %s message.\n", "debug" );
と書いて結果を標準出力に送りたいのであれば、 to send the output to stdout, then you would write
DEBUG( 0, ( "This is a %s message.\n", "debug" ) );
と書くことで、結果はデバッグファイルに送られる。すべての通常のprintf() フォーマットのエスケープ処理はちゃんと動作する。
上記の例において、DEBUGメッセージレベルは0に設定されていることに注意。メッセージレベル 0は常時出力される。基本的に、もしもメッセージレベルがグローバル値DEBUGLEVEL以下の場合、 DEBUG文は処理される。
上記の例の出力は以下のようなものになる:
[1998/07/30 16:00:51, 0] file.c:function(128) This is a debug message.
おのおののDEBUG()呼び出しは、以前の呼び出しによって生成された出力の行末が、 "\n"で終わっていないならば、新しいヘッダーを作成する。デバッグファイルへの出力は、 改行が来るたびごとにフラッシュされるフォーマットバッファーを通して渡される。 もしも、DEBUG()が呼ばれたときにバッファーがからでなければ、新しい入力は単に 追加される。
...しかし、これは全くその場しのぎである。DEBUG()が分割された行を書き込むのに 使われると言う理由で、適切な位置に置かれる。以下は今説明したことに関する、 この種の簡単な例である:
DEBUG( 0, ("The test returned " ) ); if( test() ) DEBUG(0, ("True") ); else DEBUG(0, ("False") ); DEBUG(0, (".\n") );
フォーマッティングバッファーなしでは、出力(test()がtrueを返すことを仮定)は以下のようになる:
[1998/07/30 16:00:51, 0] file.c:function(256) The test returned [1998/07/30 16:00:51, 0] file.c:function(258) True [1998/07/30 16:00:51, 0] file.c:function(261) .
これは使い物にはならない。フォーマットバッファーというその場しのぎの方法は、 この問題を解決する。
上記で説明されている行が壊れてしまう問題への、その場しのぎの解決方法への追加として、 もっときれいな解決方法がある。DEBUGADD()マクロは決してヘッダーを生成しない。フォーマット バッファーがからであったとしても、これは現在のデバッグメッセージに対して新しいテキストを 追加する。DEBUGADD()マクロの文法はDEBUG()マクロのものと同じである。
DEBUG( 0, ("This is the first line.\n" ) ); DEBUGADD( 0, ("This is the second line.\nThis is the third line.\n" ) );
これは以下を生成する。
[1998/07/30 16:00:51, 0] file.c:function(512) This is the first line. This is the second line. This is the third line.
DEBUG()マクロにおける問題の1つは、DEBUG()行が長すぎる傾向にあると言うことである。 nmbd_sendannounce.cからの以下の例について考えてみよう:
DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n", type, global_myname, subrec->subnet_name, work->work_group));
この問題の1つの解は、DEBUG()とDEBUGADD()を以下のように使って行を分割することである:
DEBUG( 3, ( "send_local_master_announcement: " ) ); DEBUGADD( 3, ( "type %x for name %s ", type, global_myname ) ); DEBUGADD( 3, ( "on subnet %s ", subrec->subnet_name ) ); DEBUGADD( 3, ( "for workgroup %s\n", work->work_group ) );
同様だが、もっとすてきな方法は、DEBUGLVL()マクロを使う方法である。 このマクロは、メッセージレベルがグローバル値DEBUGLEVEL以下の場合に真を返すので:
if( DEBUGLVL( 3 ) ) { dbgtext( "send_local_master_announcement: " ); dbgtext( "type %x for name %s ", type, global_myname ); dbgtext( "on subnet %s ", subrec->subnet_name ); dbgtext( "for workgroup %s\n", work->work_group ); }
と書ける(dbgtext()関数は以下で説明する)。
この方式ではいくつかの利点がある:
値の評価が1回のみ実行される。
変数を、DEBUGLVL()ブロック内でのみ使われるスタックの外側に配置できる。
デバッグ出力にのみ該当する処理はDEBUGLVL()ブロック内に配置できる。
この関数はフォーマットバッファー経由でデバッグファイル(と可能であればsyslog)に デバッグメッセージテキストを出力する。関数はprintf()やDebug1(0のような可変引数を取る。 入力はvslprintf()関数を使ってバッファー中に格納され、format_debug_text()に渡される。 もしもDEBUGLVL()を使っているならば、おそらくdbgtext()を使ってメッセージ本体を出力 しているだろう。
これは、デバッグメッセージヘッダーを出力する関数である。ヘッダーはフォーマットバッファー 経由では処理されない。また、もしも、フォーマットバッファーがからでない場合、dbghdr() の呼び出しは何らの出力も行わないことに注意。より詳細についてはdbghdr()中のコメントを 参照。
この関数は直接呼ばれることはない。DEBUG()とDEBUGADD()によって使われる。