утечка памяти в Visual C ++ 2013 wostringstream, imbue & amp; языковые аспекты

Что касается моего предыдущего вопроса, я предположил, что утечка памяти происходит в 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 ().

Кто-нибудь может мне помочь с этим вопросом?

-1

Решение

Итак, мы начнем с объекта, который 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;
0

Другие решения


По вопросам рекламы [email protected]