我知道这是一个经常被问到的问题,但由于有很多变种,我想重新陈述它,并希望有一个反映当前状态的答案.就像是
Logger& g_logger() {
static Logger lg;
return lg;
}
Run Code Online (Sandbox Code Playgroud)
变量lg的构造函数是否保证只运行一次?
我从以前的答案中知道,在C++ 03中,这不是; 在C++ 0x草案中,这是强制执行的.但我想要一个更明确的答案
我非常有信心在程序启动时分配(并初始化,如果适用)全局声明的变量.
int globalgarbage;
unsigned int anumber = 42;
Run Code Online (Sandbox Code Playgroud)
但是在函数中定义的静态的呢?
void doSomething()
{
static bool globalish = true;
// ...
}
Run Code Online (Sandbox Code Playgroud)
globalish分配的空间是什么时候?我猜测程序什么时候开始.但是它也被初始化了吗?或者它doSomething()是在第一次调用时初始化的?
我们遇到了静态初始化命令惨败的一些问题,我正在寻找方法来梳理大量代码以找到可能发生的事件.有关如何有效地做到这一点的任何建议?
编辑:我得到了一些关于如何解决静态初始化顺序问题的好答案,但这不是我的问题.我想知道如何查找受此问题影响的对象.在这方面,Evan的答案似乎是迄今为止最好的答案; 我不认为我们可以使用valgrind,但我们可能有可以执行类似功能的内存分析工具.只有在给定构建的初始化顺序错误的情况下才能捕获问题,并且顺序可以随每个构建而改变.也许有一个静态分析工具可以捕捉到这一点.我们的平台是在AIX上运行的IBM XLC/C++编译器.
我可以控制静态对象被破坏的顺序吗?有没有办法强制执行我想要的订单?例如,以某种方式指定我想要最后销毁某个对象,或者至少在另一个静态对象之后销毁?
我很困惑,我认为我的调试器对我说谎.我的代码中有以下循环:
MyClass::UploadFile(CString strFile)
{
...
static DWORD dwLockWaitTime = EngKey::GetDWORD(DNENG_SERVER_UPLOAD_LOCK_WAIT_TIME, DNENG_SERVER_UPLOAD_LOCK_WAIT_TIME_DEFAULT);
static DWORD dwLockPollInterval = EngKey::GetDWORD(DNENG_SERVER_UPLOAD_LOCK_POLL_INTERVAL, DNENG_SERVER_UPLOAD_LOCK_POLL_INTERVAL_DEFAULT);
LONGLONG llReturnedOffset(0LL);
BOOL bLocked(FALSE);
for (DWORD sanity = 0; (sanity == 0 || status == RESUMABLE_FILE_LOCKED) && sanity < (dwLockWaitTime / dwLockPollInterval); sanity++)
{
...
Run Code Online (Sandbox Code Playgroud)
在我的程序过程中,这个循环已被执行了数百次,并且两个静态变量在代码中的任何地方都没有改变,当它们被静态初始化并在循环条件下读取时,它们只被写入一次其他地方.由于它们是从Windows注册表中读取的用户设置,因此它们几乎总是具有dwLockWaitTime = 60和dwLockPollInterval = 5的常量值.因此循环始终为60/5.
很少,我得到一个崩溃转储,显示这行代码已经抛出除零错误.我已经检查了WinDbg所说的内容,它显示:
FAULTING_IP:
procname!CServerAgent::ResumableUpload+54a [serveragent.cpp @ 725]
00000001`3f72d74a f73570151c00 div eax,dword ptr [proc!dwLockPollInterval (00000001`3f8eecc0)]
EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 000000013f72d74a (proc!CServerAgent::ResumableUpload+0x000000000000054a)
ExceptionCode: c0000094 (Integer divide-by-zero)
ExceptionFlags: 00000000
NumberParameters: 0
ERROR_CODE: (NTSTATUS) 0xc0000094 - …Run Code Online (Sandbox Code Playgroud) 因此,经典简单的Singleton实现如下:
class Singleton
{
private:
static Singleton* singleton;
Singleton() {}
public:
static Singleton* getInstance();
};
Run Code Online (Sandbox Code Playgroud)
cpp文件:
Singleton* Singleton::singleton = 0;
Singleton* Singleton::getInstance()
{
if (!singleton)
{
singleton = new Singleton;
}
return singleton;
}
Run Code Online (Sandbox Code Playgroud)
我在这里看到的内存泄漏- "因为没有删除的新.但是在C++中没有静态析构函数,所以我们只是不关心这个内存泄漏?