1

古い不整合なものを置き換えるために、新しい割り込みシステム(c ++)を開発しています。

それはこのように動作します:

  1. メソッドを割り込み可能にしたいプログラマーはBreakFlag、メソッドの引数としてオブジェクトを受け入れます。

  2. メソッド中のある時点で、プログラマーはをチェックbreak_flag.is_set()し、終了し、そうである場合は片付けます。

break_flag.is_set()プログラムに何らかの変更が加えられた後、すべての元の呼び出しが同じ順序のままであることをテストできるようにしたいと考えています。(同じループ内の複数の呼び出しを1つの呼び出しとしてカウントするため、サイズの異なる2つの操作は同じように見えます)

最初のアプローチは、コールスタックを使用して各インスタンスを識別することでした。たとえば、コードでは次のようになります。

void A(BreakFlag& flag) {
  flag.is_set();
  B(flag);
  C(flag);
}

void B(BreakFlag& flag) {
  flag.is_set();
  C(flag);
}

void C(BreakFlag& flag) {
  flag.is_set();
}

呼び出されるたびに呼び出しスタックを確認し、is_setこのメソッドに対して次のシーケンスを生成します。

A
A, B
A, B, C
A, C

次に、これを使用して、プログラムをテストするたびにこの一連のチェックが行われることを確認し、誰かがやって来てこれを行うことができないようにすることができます。

void A(BreakFlag&flag){flag.is_set(); B(フラグ); C(フラグ); }

void B(BreakFlag& flag) {
  flag.is_set();
  //C(flag); // I HAVE COMMENTED THIS OUT BECAUSE I DONT LIKE FLAG!
}

void C(BreakFlag& flag) {
  flag.is_set();
}

シーケンスが発生するため、次のようになります。

A
A, B
A, C

これは私たちのオリジナルとは一致しません。

私たちが抱えている問題は、コンパイラがコールスタックを変更するように最適化することがあり、それが正しいにもかかわらず、コールスタックが期待どおりではないため、提案されたシステムが誤った失敗したテストを登録することです。

次のようなことで解決できます。

#define CHECK_FLAG(x) actually_check_flag(__LINE__,__FILE__,x)

これにより、基本的に各インスタンスをコードでID化できます。

それ以外は.is_set、最適化されたコードで変更されない各呼び出しを識別する方法を考えることはできませんか?

4

1 に答える 1

1

RAIIを使用して、コールスタックを手動で維持できます。各関数に入ると、ガードオブジェクトを作成します。

void B(BreakFlag& flag) {
    BreakFlagStackGuard guard(flag, "B");
    flag.is_set();
    C(flag);
}

のコンストラクタは関数名をにBreakFlagStackGuardプッシュし、デストラクタ(リターン時に呼び出される)は関数名をポップします。"B"flag.stack~BreakFlagStackGuard()B

コンパイラが最適化するために行うことは何でも、監視対象のコールスタックがソースコードを反映していることを保証できるように、ガードオブジェクトを尊重する必要があります。

于 2012-08-16T14:52:56.250 に答える