0

特定のクラス内の割り当てを追跡するために、揮発性の静的変数を使用して非常に単純なメモリ サイズ カウンターを作成しようとしています。

この静的な揮発性整数をアトミックにデクリメントするクラスのデストラクタを作成しましたが、コンパイラ (VC VS2010) はそれを最適化します (インライン化する必要はありませんが、デストラクタ内の変数は揮発性です。おそらくそれを考慮に入れる必要があります)。 ..?)。代わりに、そのデストラクタは呼び出されないようです (つまり、クラスのメンバーは正しく破棄されますが、明らかにカスタム デストラクタを使用していません)。

コード スニペットを記述できません (「機密」ソース コードからのものです)。しかし、基本的には、すべて次のようになります。

ヘッダー:

class CSomething
{
  CObject m_object;
  ...
  public:
  static volatile int ms_counter;
  ~CSomething();

}

.cpp:

CSomething::CSomething()
{
    DoStuffWith(m_object);
    AtomicAdd(ms_counter, m_object.GetTotalSize());
}

CSomething::~CSomething()
{
    AtomicDecrement(ms_counter, m_object.GetTotalSize());
} 

再開するには:~CSomething()デストラクタ内にブレークポイントを配置できないため、デストラクタはインライン化または最適化 (?) されます。の値はms_counter増加するだけで、減少することはありません (ただし、m_objectのデストラクタは明らかに呼び出されます)。m_object(いいえ、私は自分のデストラクタ内のカウンターを減らすことはできません:( )。

ここでも問題は次のとおりです。実際に何が起こる可能性があるのでしょうか。この問題を回避するにはどうすればよいですか? コンパイラフラグを介してインラインを強制しないことも、トリックを行いません..(パフォーマンスを損なう可能性があるため、インライン化しないでください)。

4

1 に答える 1

0

ここでの問題は、CSomething のデストラクタの本体に到達したときに、m_object が既に破棄されていることです。(明らかに間違っているため編集)次のコードを検討してください。

#include <iostream>

using std::cout;
using std::endl;

class A
{
    public:
    A(){cout << "A()" << endl;}
    ~A(){cout << "~A()" << endl;}
};

class B
{
    A a;
    public:
    B(){cout << "B()" << endl;}
    ~B(){cout << "~B()" << endl;}
};

int main(void)
{
    B b;
    return 0;
}

コンパイルして実行:

$ g++ test.cc -o test && ./test
A()
B()
~B()
~A()

したがって、デストラクタが呼び出される前に m_object のサイズを追跡して保存する必要があります。

于 2013-08-14T12:23:36.950 に答える