機能

2017-12-07 30 views
1

をターゲットにコンテキストGCCプリプロセッサマクロの値を呼び出す伝播するのは、私がb.cf.cbar嘘でfoo嘘、つまりはb.hf.cに含まれている機能

foo() { 
    bar(); 
} 

があるとしましょう。

bar() { 
    printf ("Called from line %d in file %s",?,?); 
    /* Run as usual */ 
} 

私はpredefined GCC preprocessor macros__LINE____FILE__からこの二つの情報を入手したい:私はそうのように、それはそれを呼び出す任意の関数fooから呼び出されたことを印刷するbarを修正したいと思います。しかし、これらは明らかにprintfの行に、に単に差し込まれている場合はb.cに、b.cにそれぞれパスが評価されます。

は私が何とか barprintfに呼び出し元のコンテキストから __LINE____FILE__の値を伝播するので、「ファイルfoo.cの行xから呼び出され、」代わりに印刷されていることはできますか?

私はbar2barの名前を変更して、ヘッダファイルb.hに委譲機能を定義しようとしました:

bar() { 
    printf ("Called from line %d in file %s",__LINE__,__FILE__); 
    bar2(); 
} 

アイデアは#includeディレクティブは、ソースファイルf.cにヘッダコードをコピーして置き換えるというものでしたパスはそれぞれf.cと行番号になります。しかし、これにより、異なる翻訳単位にわたって重複した定義エラーが発生しました。

次に、static修飾子をヘッダ定義bar2に追加して、複数の定義を可能にしようとしました。私はエラーなしでコンパイルしてプログラムを実行できますが、それでもなおbar.hが出力されます。

どこが間違っていますか?これを行うもっとエレガントな方法があると確信しています。

質問:

  1. 理由だけではなく、GDBのようなデバッガを使用していませんか?これはカーネルコードです。

  2. なぜ発信者側のデバッグをしないのですか?大規模なコードベース。

EDIT:

なぜこれが動作しませんか?

#ifdef DEBUG_PALLOC 
#define palloc_get_page(FLAGS) (palloc_get_page_debug (FLAGS, __FILE__,__LINE__)) 
#else 
void *palloc_get_page (enum palloc_flags); 
#endif 
+1

パラメータとして渡す必要があります。 OT:FAQが何を意味するのか知っていますか? –

+0

おっと、私の悪い。 FAQを質問に置き換えました。 返信いただきありがとうございます。なぜこれができないのか教えていただけますか?関数のローカル定義をどこに含めても構いませんが、それは印刷後にグローバルシンボルを指しますか? –

答えて

3

あなたがデリゲートを作成ではなく__FILE__として.h__LINE__内の関数は.hにあるであろう(とstatic修飾子はここで解決しない)こともできますが、拡大していきますマクロと適切なファイルで適切な場所に&行情報。

#define bar2() bar(__FILE__,__LINE__) 

barは、ファイル&ラインパラメータを受け入れる必要があります。

void bar(const char *file, int line) 
{ 
    printf ("Called from line %d in file %s",line,file); 
} 

GDBの方法はより複雑です。これは、と仕事ができる:

  • 現在のブレークポイントの位置/トレースバックを出力し続けてgdbのスクリプト、
  • インテル/ Windows上で(ブレークポイントをトリガー協力しbar機能:Breakpoint機能やasm("int $3")ディレクティブで、 。フラグ/ ENV VARは、デバッガが有効になっていることを伝える設定されているが、barが頻繁に呼び出された場合、これはプログラムの多くを)遅らせることができれば

注:あなたはそれを活性化したりないようにしたい場合は、これはより複雑になっていますが、コマンドライン

ファイルbar.h

#pragma once 
#ifdef DEBUG 

#define bar2() bar(__FILE__,__LINE__) 
void bar(const char *file, int line); 

#else 
void bar2(); 
#endif 

ファイルメインプログラムからbar.c

#include "bar.h" 
#include <stdio.h> 

#ifdef DEBUG 
void bar(const char *file, int line) 
#else 
void bar2() 
#endif 

{ 
#ifdef DEBUG 
    printf ("Called from line %d in file %s\n",line,file); 
#endif 
    printf("NOP\n"); 
} 

コールbar2-DDEBUGフラグは、次の印刷行かないで作ることができます。 DEBUGが設定されている場合、bar2barを呼び出すマクロです。 DEBUGが設定されていない場合、bar2が直接あなたの機能です。

これらのパターンを生成するためにスクリプトを使用しない限り、すべての機能に対してこれを行うのは面倒です。

+0

恐ろしい!これをできるだけ早く試みます。教育目的のために、 'static'キーワードを使用して複数の定義をここでは使えないのはなぜですか? –

+0

同じ理由ではありません: '__FILE__'と' __LINE__'は、それらが含まれている元のファイルを参照しています。マクロだけがそのダイナミックを作ることができます。 –

+0

はい、マクロだけを定義しますが、その後に関数プロトタイプを定義しないでください。 –

関連する問題