0

GCCには、関数が呼び出されるたびに、または関数が戻るたびにルーチンを呼び出すことができるインストルメンテーションに関する優れた機能があります。

今、私は自分のシステムを作成して他のコンパイラに移植できるようにし、必要な関数 (パラメーターの数が異なる可能性があります) をインストルメント化できるようにしたいので、両方の状況で 2 つのマクロを考えていました。define句だけで活性化されるような何らかのプロファイルを作ろうと考えています。

#define FUNCT(t,function_name,...)   \
    (t) function_name(...) { \
        (void) *func_pointer = &(function_name); \
        start_data(func_pointer, myclock());

#define RETURN(x) {stop_data(func_pointer, myclock()); return (x);}

FUNCT(BOOL, LMP, const int prof, const int nmo))
    if (nmo <= 5 ||
        prof > (prof_l / 3)) {
        .... do long operations....
        RETURN(FALSE);
    }
    ... do more....
    RETURN(TRUE);
}

しかし、私はそれを機能させることができません。誰かがこれで私を助けることができますか? それとも達成するのが難しい仕事ですか?

私の頭に浮かぶ他の選択肢は、マクロなしで関数を宣言させることです。名前を知らなくても関数ポインタを知る必要がある場合は、VB で Me を使用してフォームを呼び出すときのように、それは一般的なエイリアスです。出来ますか?

4

3 に答える 3

3

gcc -Eマクロのデバッグに使用します。投稿したコードを使用する:

$ gcc -E t.c
# ... skip stuff ....

(BOOL) LMP(...) { (void) *func_pointer = &(LMP);
                  start_data(func_pointer, myclock());)
    if (nmo <= 5 ||
        prof > (prof_l / 3)) {
        .... do long operations....
        {stop_data(func_pointer, myclock()); return (FALSE);};
    }
    ... do more....
    {stop_data(func_pointer, myclock()); return (TRUE);};
}

(読みやすくするために空白を追加しました。)

2つの問題がすぐにわかります。関数の引数が思ったように展開されなかったことと、)どこかから余分なものがあります。

拡張可変個引数を取得するには__VA_ARGS__、ではなく、を使用します...。迷い)はコールサイトにあります。

それで:

#define FUNCT(t,function_name,...)   \
    (t) function_name(__VA_ARGS__) { \
        (void) *func_pointer = &(function_name); \
        start_data(func_pointer, myclock());

#define RETURN(x) {stop_data(func_pointer, myclock()); return (x);}

FUNCT(BOOL, LMP, const int prof, const int nmo)
    if (nmo <= 5 ||
        prof > (prof_l / 3)) {
        .... do long operations....
        RETURN(FALSE);
    }
    ... do more....
    RETURN(TRUE);
}

これを試す価値があるかどうかについては(可変個引数マクロはC99に付属しており、すべてのコンパイラがその標準を実装しているわけではなく、サポートはコンパイラごとに異なる可能性があります)、私にはわかりません。各コンパイラのネイティブプロファイリングツールを使用する方がおそらく良いでしょう。できればオーバーヘッドを減らして、より良い結果を得ることができます。

于 2012-08-08T14:59:18.427 に答える
1

関数側ではなく、呼び出し側で関数を計測する方がはるかに簡単です。マクロは関数と同じ名前を持つことができます。置換関数をどこかで宣言します

double myfunc_wrapper(int someArg) {
  double ret = 0;
  // do something before
   ...
  // now call it
  ret = (myfunc)(someArg);

  // Then do something after
  ....
  return ret;
}

必ず()呼び出し自体を囲んで、マクロではなく常に関数が呼び出されるようにします。

そして、マクロを使用して関数を「オーバーロード」します

#define myfunc(...) mfunc_wrapper(__VA_ARGS__)

そのアイデアで、興味のあるコンパイル単位でその場で関数を置き換えることができます。

于 2012-08-08T15:17:51.660 に答える
0

Mat に加えて、次の使用には人間工学的な問題があり#define RETURN(x) {...}ます。

if (test)
  RETURN (TRUE);
else
  RETURN (FALSE);

に評価されます

if (test)
  {...}
;           // <syntactical error
else
  {...}
;
于 2012-08-08T15:11:37.290 に答える