VS2008 中的 C++ STL:std::ostringstream 在大量分配/清除使用后抛出 std::bad_alloc

标签 c++ stl iostream ostringstream

我遇到过这样一种情况(在 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 的时间同时发生。这表明堆内存已经耗尽,或者请求的 block 大小在连续空间中不可用。

有没有其他人遇到过 ostringstream 对象的这种泄漏现象,还有什么其他替代对象可以代替这个不稳定的对象?

非常感谢!

最佳答案

我看不出这段代码如何重现问题。在 looper 递增到 45 之后,它应该消耗完所有内存。

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

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

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

关于VS2008 中的 C++ STL:std::ostringstream 在大量分配/清除使用后抛出 std::bad_alloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3247805/

相关文章:

c++ - OpenGL 3.0 : Cannot use framebuffer object in shader (black)

c++ - 用指针直接访问STL列表的元素

c++ - 整数对散列函数的错误

c++ - 为什么 getline 不移动到下一行?

c++ - 初始化列表和基于范围的函数

c++ - 什么是 C++ iostream endl 惨败?

c++ - 在哪里可以找到 current 在 Mac 上使用 GCC 编译器的版本?

c++ - 在多大程度上允许将 C 和 C++ 结合使用?

C++ STL 列表迭代器

c++ - Visual Studio : "str() is not a member of std::ostringstream"