序文:
この質問はこれらのものと密接に関連しています: ...
- C++: 静的な初期化順序の問題と競合状態を同時に回避
する
-メモリのブロックが割り当てられた場所を検出する方法は?
...しかし、彼らには前向きな解決策がなく、実際のターゲットのユースケースはわずかに異なります。
オブジェクトの構築中に、オブジェクトが静的メモリ ブロック ( BSS ) で初期化されているか、ヒープでインスタンス化されているかを知る必要があります。
理由は次のとおりです。
オブジェクト自体は、コンストラクターで「すべてゼロ」に初期化されるように設計されています。したがって、オブジェクトが静的に初期化されている場合、初期化は必要ありません。プログラムがロードされたときに、すべてのオブジェクトを含むブロック全体が既にゼロに設定されています。
オブジェクトの静的インスタンスは、静的に割り当てられた他のオブジェクトで使用でき、オブジェクトの一部のメンバー変数を変更できます
静的変数の初期化の順序は 事前に決定されていません-つまり、コンストラクターが呼び出される前にターゲットオブジェクトを呼び出すことができるため、そのデータの一部が変更され、静的変数の初期化の未知の順序に従ってコンストラクターが後で呼び出される可能性があるため、既にクリアされています変更されたデータ。そのため、静的に割り当てられたオブジェクトのコンストラクターでコードを無効にしたいと考えています。
注:いくつかのシナリオでは、オブジェクトは深刻なマルチスレッドアクセスの対象であり(いくつかの InterlockedIncrement/Decrement ロジックがあります)、スレッドがそれに触れる前に完全に初期化する必要があります-ヒープに明示的に割り当てた場合に保証できること、しかし静的領域ではありません(ただし、静的オブジェクトにも必要です)。
ケースを説明するためのコードのサンプル:
struct MyObject
{
long counter;
MyObject() {
if( !isStaticallyAllocated() ) {
counter = 0;
}
}
void startSomething() { InterlockedIncrement(&counter); }
void endSomething() { InterlockedDecrement(&counter); }
};
現時点では、「この」ポインターが事前定義された範囲内にあるかどうかを確認しようとしていますが、これは確実に機能しません。
LONG_PTR STATIC_START = 0x00400000;
LONG_PTR STATIC_END = 0x02000000;
bool isStatic = (((LONG_PTR)this >= STATIC_START) && (LONG_PTR)this < STATIC_END));
更新: 明示的な new 演算子が適用されないサンプル ユース ケース。コードは「疑似コード」であり、ユースケースを説明するためのものです。
struct SyncObject() {
long counter;
SyncObject() {
if( !isStaticallyAllocated() ) {
counter = 0;
} }
void enter() { while( counter > 0 ) sleep(); counter++; }
void leave() { counter--; }
}
template <class TEnum>
struct ConstWrapper {
SyncObject syncObj;
TEnum m_value;
operator TEnum() const { return m_value; }
LPCTSTR getName() {
syncObj.enter();
if( !initialized ) {
loadNames();
intialized = true;
}
syncObj.leave();
return names[m_value];
}
}
ConstWrapper<MyEnum> MyEnumValue1(MyEnum::Value1);