0

我遇到了一种情况(在 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 对象的这种泄漏现象,还有哪些其他替代对象可用而不是这个片状对象?

非常感谢!

4

1 回答 1

2

我看不出这段代码如何重现问题。在 looper 增加到 45 之后,它应该即将完成消耗任何内存。

通用诊断是程序很少设法消耗所有可能的可用虚拟内存。它将首先在堆内找到一块足够大以存储字符串流缓冲区的连续字节时死亡。它被称为地址空间碎片,您对此无能为力。您的 Sleep() 调用肯定不会做任何有用的事情,合并分配的堆块需要垃圾收集器。

另一个非常标准的陷阱是使用 TaskMgr.exe 来诊断内存使用情况。它通常显示工作集,即映射到 RAM 的虚拟内存量。这通常只是您的程序消耗的虚拟内存量的一小部分,并且不能真正衡量您的程序消耗了多少虚拟内存。或者告诉你任何关于地址空间碎片的事情。

SysInternals 的 VMMap 实用程序可以显示您的程序如何使用虚拟内存。

于 2010-07-14T16:13:24.033 回答