osg*_*sgx 44 c++ exception out-of-memory new-operator
new操作员可以在现实生活中抛出异常吗?
如果是这样,除了杀死我的应用程序之外,我是否有任何处理此类异常的选项?
更新:
任何真实的,重要的new应用程序检查失败并在没有内存时恢复吗?
Jam*_*lis 41
是的,new如果分配失败,可以并且将会抛出.如果内存不足或者尝试分配的内存块太大,就会发生这种情况.
您可以捕获std::bad_alloc异常并适当地处理它.有时这是有道理的,有时候(读:大多数时候)它没有.例如,如果您尝试分配一个巨大的缓冲区但可以使用较少的空间,则可以尝试连续分配较小的块.
Bri*_*ndy 24
新的运算符和new []运算符应该抛出std::bad_alloc,但情况并非总是如此,因为行为有时可以被覆盖.
人们可以使用std::set_new_handler,突然发生一些完全不同的事情,而不是扔std::bad_alloc.虽然标准要求用户使内存可用,中止或抛出std::bad_alloc.但当然情况可能并非如此.
免责声明:我不打算这样做.
Per*_*uid 19
如果您运行的是运行Linux且没有虚拟内存的典型嵌入式处理器,那么如果您分配了太多内存,则新的操作系统很可能会终止您的进程.
如果您在物理内存小于最大虚拟内存(标准Windows上为2 GB)的计算机上运行程序,您会发现一旦分配了大约等于可用物理内存的内存量,进一步分配将成功但会导致分页到磁盘.这会使您的程序陷入困境,实际上您可能无法达到耗尽虚拟内存的程度.所以你可能不会抛出异常.
如果您拥有比虚拟内存更多的物理内存,并且只是继续分配内存,那么当您将虚拟内存耗尽到无法分配所请求的块大小时,您将收到异常.
如果你有一个长期运行的程序,它分配和释放许多不同的块大小,包括具有各种生命周期的小块,虚拟内存可能会碎片化到新的无法找到足够大的块的程度.满足要求.然后new将抛出异常.如果你碰巧有一个内存泄漏漏掉了随机位置的偶然小块,最终会将内存碎片到任意小块分配失败的程度,并抛出异常.
如果你有一个程序错误,意外地将一个巨大的数组大小传递给new [],new将失败并抛出异常.例如,如果数组大小实际上是某种随机字节模式,可能是由未初始化的内存或损坏的通信流导出的.
以上所有内容均为默认的全局新内容.但是,您可以替换global new,您可以提供特定于类的新功能.这些也可以抛出,这种情况的意义取决于你如何编程.新的通常包括一个循环,尝试所有可能的途径来获取所请求的内存.当所有人都筋疲力尽时,它会抛出.你做什么取决于你.
您可以从new中捕获异常并使用它提供的机会来记录异常时的程序状态.你可以"转储核心".如果在程序启动时分配了循环检测缓冲区,则可以在终止程序之前将其转储到磁盘.程序终止可以是优雅的,这比仅仅不处理异常更有优势.
我没有亲自看过一个例子,在异常之后可以获得额外的内存.然而,一种可能性如下.假设您有一个高效但不擅长回收可用空间的内存分配器.例如,它可能容易出现自由空间碎片,其中自由块相邻但未合并.您可以使用new中的异常(在new_handler中捕获)在重试之前运行可用空间的压缩过程.
严肃的程序应该将内存视为潜在的稀缺资源,尽可能地控制其分配,监控其可用性并在事情看起来严重错误时做出适当的反应.例如,您可以假设在任何实际程序中传递给内存分配器的size参数都有相当小的上限,而大于此值的任何内容都会导致某种错误处理,无论请求是否可以满意.您可能会争辩说应该监视长期运行程序的内存增加率,如果可以合理地预测该程序将在不久的将来耗尽可用内存,则应该开始有序重启该过程.
在Unix系统中,习惯上运行具有内存限制(使用ulimit)的长时间运行的进程,这样它就不会占用系统的所有内存.如果你的程序达到了这个限制,你就会得到std::bad_alloc.
OP编辑的更新:从内存不足情况恢复的程序的最典型情况是垃圾收集系统,然后执行GC并继续.虽然,这种按需GC实际上只适用于最后的努力; 通常,好的程序会定期尝试GC以减少对收集器的压力.
非GC程序从内存不足的问题中恢复的情况不常见,但对于面向Internet的服务器,恢复的一种方法是简单地拒绝导致内存耗尽"临时"错误的请求.("先进先出"策略.)
这取决于编译器/运行时以及operator new您正在使用的内容(例如,某些版本的Visual Studio 不会抛出开箱即可,而是宁愿返回一个NULL指针malloc.)
您可以始终catch使用std::bad_alloc异常,或明确使用nothrow new返回NULL而不是抛出.(另请参阅过去围绕主题的StackOverflow帖子.)
需要注意的是operator new,像malloc,会当你耗尽内存,(在根据操作系统的32位进程如2-3GB)失败了的地址空间,配额外的(ulimit已经提到)或出连续的地址空间(例如碎片堆.)
| 归档时间: |
|
| 查看次数: |
33866 次 |
| 最近记录: |