Что касается моего предыдущего вопроса, я предположил, что утечка памяти происходит в std :: string, но при более глубоком рассмотрении я получил некоторые странные результаты. Давай начнем:
Считайте, что у нас есть глобальный
static volatile std::wostringstream *Log = nullptr;
и в функции WriteToLog () у нас есть следующий код:
std::wostringstream* new_log = new std::wostringstream(std::ios::in | std::ios::out);
new_log->imbue(CConsumer::GetUtf8Locale());
std::wostringstream* old_log = (std::wostringstream*)Log;
while((std::wostringstream *)::InterlockedCompareExchangePointer((PVOID volatile *)&Log, new_log, (PVOID)old_log) != new_log)
{
::SleepEx(10, FALSE);
}
std::string logtext(Hooker::Utf16ToUtf8(old_log->str()));
который использует собственные:
static std::locale FORCEINLINE GetUtf8Locale()
{
static std::unique_ptr<std::codecvt_utf8_utf16<wchar_t>> code_cvt(new std::codecvt_utf8_utf16<wchar_t>(std::codecvt_mode::generate_header | std::codecvt_mode::little_endian));
return std::locale(std::locale(), code_cvt.get());
}
Так как события журнала происходят время от времени, это вызывает огромную утечку памяти (с начальных 5 МБ / 500 дескрипторов он переходит к 200 МБ / 300 000 дескрипторов за считанные минуты).
Ранее я предполагал, что это утечка по отношению к std :: string, но, используя Visual Studio Profiler, он показывает, что все утечки вызваны GetUtf8Locale ().
Кто-нибудь может мне помочь с этим вопросом?
Итак, мы начнем с объекта, который Log
член указывает на 0x87654321
, Тогда две темы вызывают WriteToLog
Thread1 Thread2
...new_log=new ...
(now new_log=0x15331564)
...new_log=new ...
(now new_log=0x25874963)
...old_log=Log;
(now old_log=0x87654321)
...old_log=Log;
(now old_log=0x87654321)
InterlockedCompareExchangePointer
(now new_log=0x87654321)
(now Log=0x15331564)
InterlockedCompareExchangePointer
(now new_log=0x15331564)
(now Log=0x25874963)
...stuff... ...stuff...
delete old_log
(now 0x87654321 is deleted)
delete old_log
(now 0x87654321 is deleted TWICE!)
И Log
член указывает на 0x25874963
, так что … лог 0x15331564
утечка!
Ваше использование InterlockedCompareExchangePointer
это неверно. Я думаю, что это правильно, в зависимости от кода, который вы не показали.
std::wostringstream* new_log = new std::wostringstream(std::ios::in | std::ios::out);
new_log->imbue(CConsumer::GetUtf8Locale());
std::wostringstream* old_log = ::InterlockedExchangePointer((PVOID volatile *)&Log.get(), new_log);
std::string logtext(Hooker::Utf16ToUtf8(old_log->str()));
delete old_log;