前言:
这个问题与这些问题密切相关:...
- C++:同时避免静态初始化顺序问题和竞争条件
-如何检测内存块的分配位置?
...但他们没有积极的解决方案,我的实际目标用例略有不同。
在对象的构造过程中,我需要知道它是在静态内存块(BSS)中初始化还是在堆中实例化。
原因如下:
对象本身被设计为在构造函数中初始化为“全零”-因此,如果对象被静态初始化,则不需要初始化-加载程序时,具有所有对象的整个块已经设置为零。
对象的静态实例可以被其他静态分配的对象使用并改变对象的一些成员变量
静态变量的初始化顺序 不是预先确定的——即我的目标对象可以在其构造函数被调用之前被调用,从而改变它的一些数据,并且构造函数可以稍后根据一些未知的静态初始化顺序被调用,从而已经清除更改数据。这就是为什么我想在构造函数中为静态分配的对象禁用代码。
注意:在某些情况下,对象是严重多线程访问的主题(它具有一些 InterlockedIncrement/Decrement 逻辑),并且必须在任何线程可以接触它之前完全初始化它 - 如果我在 Heep 中显式分配它,我可以保证,但不在静态区域(但我也需要静态对象)。
用于说明案例的示例代码:
struct MyObject
{
long counter;
MyObject() {
if( !isStaticallyAllocated() ) {
counter = 0;
}
}
void startSomething() { InterlockedIncrement(&counter); }
void endSomething() { InterlockedDecrement(&counter); }
};
目前我正在尝试检查“this”指针是否在某个预定义的范围内,但这并不可靠。
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);