5

私は機能を持っています:foo()

の前にデバッグを追加するために、(私が推測するシム)#defineの「前に」置くa を書きたいです。したがって、これは次のようになります。foo()foo()#define

   #define foo(dev) {                         \
      printk("%s: get %lx\n", (dev)->name);   \
      foo_orig(dev);                          \
   }

そして、名前を に変更foo()foo_orig()ます。

foo()関数が次のように「分離」で呼び出された場合、これは正常に機能します。

   foo(dev);

しかし、それが内で呼び出された場合、if()それはコンパイルの問題です...

   if (something() && foo(dev)) {
     ..

問題を説明しましたか?これに対する解決策はありますか?

問題は、コードが .xml ではなく呼び出し元の関数に存在する必要があるため、定義としてシムが本当に必要であることですfoo()。[この理由は、デバッグの理由で呼び出し元の関数の EIP をダンプする必要があるためです (つまり、誰が呼び出しているかを知る必要がありますfoo()]。

4

7 に答える 7

2

私の知る限り、コンマ演算子は機能するはずです:

#define foo(dev) (printk("%s: get %lx\n", (dev)->name), foo_orig(dev))
于 2012-10-13T01:17:50.687 に答える
1

あなたがGCCを使用していると仮定すると、これが役立つはずです:

#define foo(dev) ({                           \
      printk("%s: get %lx\n", (dev)->name);   \
      foo_orig(dev);                          \
   })

重要なポイントは、中括弧を囲む括弧です。

GCC: 式でのステートメントと宣言

于 2012-10-13T01:18:37.000 に答える
1

問題は、どのように機能するか#defineです。

前処理段階で、コンパイラは の出現箇所をfoo定義済みのテキストに置き換えます。したがって、コードは次のようになります。

  // call to foo() -> valid
  printk("%s: get %lx\n", (dev)->name);
  foo_orig(dev);    

  // within a parenthesis - invalid 
  if (something() && printk("%s: get %lx\n", (dev)->name);
          foo_orig(dev);) {

1 つの解決策は、次のようにデバッグに実際の関数を使用することです。

foo_dbg(type *dev) {
   printk("%s: get %lx\n", (dev)->name);
   return foo_orig(dev);
}
#ifdef DEBUG
   #define foo(dev) foo_dbg(dev)
#else
   #define foo(dev) foo_orig(dev)
#endif
于 2012-10-13T01:21:42.327 に答える
0

#define は、検索と置換を行うようなものです。したがって、「if」ステートメントはコンパイル時に次のようになります。

if (something() && { print(....); foo_orig(dev);}) {
}

それはコンパイラエラーを説明するはずです。

于 2012-10-13T01:18:27.753 に答える
0

コンマ演算子を使用します。

#define foo(dev) (printk(blah, blah), foo_orig(dev))

C99ではインライン関数を使用できます

static inline rtype foo (type *dev) { printk(blah, blah); return foo_orig(dev); }
于 2012-10-13T01:18:37.720 に答える
0

;おそらく、あなたのセミコロン#defineをコンマ,に置き換え、中括弧/大括弧を削除してください{}

または、ifステートメントで に置き換えfoo(dev)ます(foo)(dev)

于 2012-10-13T01:21:24.740 に答える
-1

この理由は、b/ci がデバッグの理由で呼び出し元の関数の EIP をダンプする必要があるためです (つまり、誰が foo() を呼び出しているかを知る必要があります)。

アセンブリを記述して、スタック上のリターン アドレスを検索することもできます。しかし実際には、ほとんどのコンパイラには、このニーズに対応するビルトインが既にあります。GCC についてはこちらを参照してください(Clang の場合も同じです) 。VC++ についてはこちらを参照してください(Intel コンパイラでは同じです)。

実際の内部にシムを記述し、/をfoo使用して関数の戻りアドレスを取得するだけです (つまり、関数を開始した命令の 1 つ後の命令)。_ReturnAddress()__builtin_return_address(0)call

于 2012-10-13T01:18:25.133 に答える