visual c++ 2013 内存泄漏 wostringstream、imbue 和语言环境方面
Posted
技术标签:
【中文标题】visual c++ 2013 内存泄漏 wostringstream、imbue 和语言环境方面【英文标题】:visual c++ 2013 memory leak wostringstream, imbue & locale facets 【发布时间】:2015-03-31 16:53:18 【问题描述】:与我之前的问题有关,我假设内存泄漏发生在 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());
由于日志事件偶尔发生,它会产生巨大的内存泄漏(从最初的 5MB/500 个句柄在几分钟内跃升至 200MB/300,000 个句柄)。
以前,我认为这是与 std::string 相关的泄漏,但是,使用 Visual Studio Profiler,它显示所有泄漏都是由 GetUtf8Locale() 引起的。
谁能帮我解决这个问题?
【问题讨论】:
你的演员让我担心。 我不知道为什么会有InterlockedCompareExchangePointer
,它似乎是某种错误的锁定机制?
你有没有打电话给delete new_log;
?
我非常怀疑这段代码在您声称的地方泄漏。
@TiodorJovovic 对于我的口味而言,所有这些看起来都很有缺陷。
【参考方案1】:
这个答案是错误的,我忽略了 InterlockedCompareExchangePointer 的“比较”部分。不过,我认为这是朝着正确方向迈出的一步。
所以我们从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;
【讨论】:
以上是关于visual c++ 2013 内存泄漏 wostringstream、imbue 和语言环境方面的主要内容,如果未能解决你的问题,请参考以下文章