我试图构建一个包含循环缓冲区的单例类,每次某个函数想要转发发送内容到调试客户端(例如DBGview或类似函数)时,该函数会将其信息存储在循环缓冲区中。该对象还将运行一个将休眠一段时间的线程,然后唤醒并将缓冲区内容转储到调试客户端。
这是每个人在需要发送调试内容时调用的函数:
TTFW_LogRet PrintToLogger (std::string Str)
{
Logger *Log;
if(Instance_Mutex == NULL)
{
Instance_Mutex = CreateMutex(NULL,FALSE,NULL);
if (Instance_Mutex == NULL)
{
OutputDebugStringA("CreateMutex error! the Logger will close \n");
return GENERAL_ERROR;
}
}
Log = Logger::getLogInstance();
Log->LogStringToOutput(Str);
return SUCCESS;
}
由于某种原因,我总是在返回SUCCESS语句
后收到堆损坏错误这是Getinstance()函数:
Logger* Logger::getLogInstance()
{
if(_instance == NULL)
{
MutexLock(Instance_Mutex);
if(_instance == NULL)
{
_instance = new Logger();
}
MutexUnlock(Instance_Mutex);
}
return _instance;
}
并且线程函数是:
DWORD WINAPI Logger::WorkerThread (LPVOID lpParam )
{
Logger *log = static_cast <Logger*> (lpParam);
for(;;)
{
Sleep(2000);
if(log->getOutputMethod() == odBuffer && log->CyclicBuffer1.size() >= log->Thresh && !log->CyclicBuffer1.empty())
{
TTFW_LogRet ret;
ret = log->FullBufferDump();
if (ret != SUCCESS)
{
log->LogStringToOutput("Error occured in dumping cyclic buffer , the buffer will be cleared\n");
}
}
}
}
有没有人知道为什么这个代码会发生堆损坏?请注意,调试函数被多次调用,并且与转储缓冲区的线程没有同步。
答案 0 :(得分:0)
您使用double checked locking会导致您看到的那种细微问题。特别是,C ++允许行
_instance = new Logger();
可能会导致_instance
在Logger
构造函数完成之前获得非NULL值。然后,如果另一个线程调用getLogInstance
,则不满足条件if(_instance == NULL)
,并且线程将使用未完全初始化的对象。考虑使用直接锁定而不进行双重检查,或其他一些 - 可能依赖于实现 - 技术。在C ++ 11中,您可以安全地使用静态变量来实现此目的。
答案 1 :(得分:0)
我的通灵调试技巧告诉我LogStringToOutput
不是线程安全的,并且在从多个线程调用时导致堆损坏。