【问题标题】:Allocating large blocks of memory with new用 new 分配大块内存
【发布时间】:2010-10-10 01:47:34
【问题描述】:

我需要用new分配大块内存。

我坚持使用 new,因为我正在为两部分应用程序的生产者端编写一个模拟。实际的生产者代码正在分配这些大块,我的代码有责任删除它们(在处理它们之后)。

有没有一种方法可以确保我的应用程序能够从堆中分配如此大量的内存?我可以将堆设置为更大的大小吗?

我的情况是 64 个 288000 字节的块。有时我要分配 12 个,而其他时候我要分配 27 个。我得到一个 std::bad_alloc 异常。

这是:C++、Linux 上的 GCC(32 位)。

【问题讨论】:

  • 您需要一口气完成所有这些吗?否则,您可以使用内存池和自定义分配器来管理池。
  • 正如我所说,我试图模拟生产代码将要做什么。如果可以的话,我会使用静态分配的内存池。
  • 您可以使用静态分配的池,并将您的删除调用替换为“FreeBlock”函数。这样你就可以检查你是否已经填满了每一个获得的块。
  • 是的,我可以这样做,但我仍然想知道为什么我无法分配可用的内存。

标签: c++ memory new-operator bad-alloc


【解决方案1】:

更新:

我已经修复了一个数组索引错误,它现在可以正确分配。

如果我不得不猜测...我在我的堆上走来走去,并且在弄乱 malloc 的数据结构。 (??)

【讨论】:

  • 那肯定行!有时我在调试阶段使用带有断言语句的 INLINED 访问器方法来解决此类问题。 (它们被编译为生产代码。)
【解决方案2】:

当您在不同时间运行程序时会出现不同的行为,这一事实让我认为分配代码并不是真正的问题。相反,其他人正在使用内存,而你是金丝雀发现它丢失了。

如果“其他人”在您的程序中,您应该可以使用Valgrind 找到它。

如果其他人是另一个程序,您应该能够通过转到不同的runlevel 来确定这一点(尽管您不一定知道罪魁祸首)。

【讨论】:

    【解决方案3】:

    关于C++/GCC/Linux(32bit)中的new...

    已经有一段时间了,它依赖于实现,但我相信 new 将在幕后调用 malloc()Malloc(),除非你请求的东西超出了进程的地址空间,或者超出了指定的 (ulimit/getrusage) 限制,否则不会失败。即使您的系统没有足够的 RAM+SWAP。例如:malloc(1gig) 在一个拥有 256Meg RAM + 0 SWAP 的系统上,我相信会成功。

    但是,当您使用该内存时,内核会通过延迟分配机制提供页面。那时,当您第一次读取或写入该内存时,如果内核无法为您的进程分配内存页面,它会终止您的进程。

    这可能是共享计算机上的问题,当您的同事发生缓慢的内核泄漏时。尤其是当他开始淘汰系统进程时。

    因此,您看到 std::bad_alloc 异常的事实是“有趣的”。

    现在 new 将在分配的内存上运行构造函数,在它返回之前触及所有这些内存页面。根据实现的不同,它可能会捕获内存不足信号。

    你用普通的 o'l malloc 试过这个吗?

    您是否尝试过运行“免费”程序?你有足够的可用内存吗?

    正如其他人所建议的,您是否检查了 limit/ulimit/getrusage() 的硬约束和软约束?

    您的代码到底是什么样的?我猜新的 ClassFoo [ N ]。或者也许 new char [ N ].

    什么是sizeof(ClassFoo)?什么是N

    对于大多数现代机器来说,分配 64*288000 (17.58Meg) 应该是微不足道的......您是在嵌入式系统上运行还是在其他特殊的系统上运行?

    或者,您是否与自定义 new 分配器链接?你的班级有自己的分配器吗?

    您的数据结构(类)是否分配其他对象作为其构造函数的一部分?

    有人篡改了您的库吗?您是否安装了多个编译器?您是否使用了错误的包含或库路径?

    您是否链接过时的目标文件?您是否只需要重新编译所有源文件?

    你能创建一个简单的测试程序吗?仅仅几行代码就可以重现该错误?还是您的问题在其他地方,只出现在这里?

    --

    为了它的价值,我在 g++ 下的 32 位 linux 中用 new 分配了超过 2gig 的数据块。您的问题出在其他地方。

    【讨论】:

      【解决方案4】:

      我建议在程序启动时分配所有内存并使用新位置来定位缓冲区。为什么要采用这种方法?好吧,您可以手动跟踪碎片等。没有可移植的方法来确定可以为您的进程分配多少内存。我很肯定有一个特定于 linux 的系统调用可以为您提供该信息(想不出它是什么)。祝你好运。

      【讨论】:

        【解决方案5】:

        您可能受到进程'ulimit的限制;运行ulimit -a 并检查虚拟内存和数据段大小限制。除此之外,您能否发布您的分配代码以便我们了解实际情况?

        【讨论】:

        • 我使用 getrlimit(RLIMIT_AS, &lim) 进行检查,它报告当前和最大值为 4GB。
        • @Jeff:你只是想分配大约 18Mb!这在任何现代计算机上都是微不足道的。 必须在你的程序中分配大量内存。
        猜你喜欢
        • 2013-05-09
        • 2013-11-16
        • 1970-01-01
        • 1970-01-01
        • 2021-03-09
        • 2016-02-13
        • 2011-02-02
        • 2019-02-03
        • 2020-10-05
        相关资源
        最近更新 更多