C++ VS2008 中的 STL:std::ostringstream 在大量分配/清除使用后抛出 std::bad_alloc
我遇到过一种情况(在 Win32 上),std::ostringstream 对象继续消耗进程内存,即使它在一系列追加类型操作后表面上被清除。请看一下这个 C++ 片段:
int main(void)
{
std::ostringstream cOutputLogStream;
// Random long string
std::string sTest = "jkspoiauyeraspfoiusdfsdfekgpweojkgpwoekpokgkpgeopoegwj";
std::string sEmpty = "";
int n = 0;
int looper = 0;
while (n++ < 100000)
{
while (looper++ < 45)
{
cOutputLogStream << s;
}
cOutputLogStream.str(sEmpty);
cOutputLogStream.clear();
// This should give the heap manager a chance to consolidate
// fragmented memory blocks
Sleep(1);
}
}
在执行内部 while() 循环期间,在任务管理器中观察进程的内存使用情况显示出连续的上升趋势,最终趋于平稳。然而,这种平稳化与重复抛出错误 std::bad_alloc 的同时发生。这表明堆内存已耗尽,或者所请求的块大小在连续空间中不可用。
有没有其他人经历过 ostringstream 对象的这种泄漏现象,还有哪些其他替代对象可以代替这种片状对象?
非常感谢!
I have come across a situation (on Win32) where the std::ostringstream object continues to consume process memory, even when it is ostensibly cleared out after a series of append-type operations. Please take a look at this C++ fragment:
int main(void)
{
std::ostringstream cOutputLogStream;
// Random long string
std::string sTest = "jkspoiauyeraspfoiusdfsdfekgpweojkgpwoekpokgkpgeopoegwj";
std::string sEmpty = "";
int n = 0;
int looper = 0;
while (n++ < 100000)
{
while (looper++ < 45)
{
cOutputLogStream << s;
}
cOutputLogStream.str(sEmpty);
cOutputLogStream.clear();
// This should give the heap manager a chance to consolidate
// fragmented memory blocks
Sleep(1);
}
}
During execution of the inner while() loop, observation of the process's memory usage in Task Manager shows a continuous upward ramp, which eventually levels off. However, this levelling-off happens at the same time as when the error std::bad_alloc is repeatedly thrown. This would suggest that heap memory has either been exhausted, or the requested size of block is not available in a contiguous space.
Has anyone else experienced this leaking phenomenon with ostringstream objects, and what other alternative objects are available instead of this flaky one?
Many thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不明白这段代码如何重现该问题。 Looper 增加到 45 后,应该就消耗完所有内存了。
一般的诊断是程序很少能够消耗所有可能的可用虚拟内存。当在堆中找到足够大的连续字节来存储字符串流缓冲区时,它将首先死亡。这称为地址空间碎片,对此您无能为力。您的 Sleep() 调用肯定不会做任何有用的事情,合并分配的堆块需要垃圾收集器。
另一个相当标准的陷阱是使用 TaskMgr.exe 来诊断内存使用情况。它通常显示工作集、映射到 RAM 的虚拟内存量。这通常只是您的程序消耗的虚拟内存量的一小部分,并且不能真正衡量您的程序消耗了多少虚拟内存。或者告诉您有关地址空间碎片的任何信息。
SysInternals 的 VMMap 实用程序可以向您显示程序如何使用虚拟内存。
I don't see how this code could repro the problem. After looper increments to 45, it should be about done consuming any memory.
The generic diagnostic is that a program very rarely manages to consume all possible available virtual memory. It will die first on finding a chunk of contiguous bytes inside the heap that's large enough to store the string stream buffer. It is called address space fragmentation, there isn't anything you can do about it. Your Sleep() call will certainly not do anything useful, consolidating allocated heap blocks requires a garbage collector.
Another pretty standard trap is using TaskMgr.exe to diagnose memory usage. It normally displays the working set, the amount of virtual memory that's mapped to RAM. That's usually only a fraction of the amount of virtual memory your program consumes and cannot give a true measure of how much virtual memory your program has consumed. Or tell you anything about address space fragmentation for that matter.
The SysInternals' VMMap utility can show you how your program is using virtual memory.