繁体   English   中英

抛出std :: bad_alloc的其他可能原因

[英]Other Possible Reasons for std::bad_alloc being thrown

我正在研究相当大的SIP电话应用程序,偶尔当我们在大量调用加载时使用集成的Web UI(使用tntnet编写)时,程序将因为抛出std :: bad_alloc而退出。 有数百个线程在使用(每个活动调用3个),因此导致异常的代码位置非常随机,但总是在使用GUI之后。

现在,我知道std :: bad_alloc可以在内存不足时抛出,在这种情况下不是这种情况。 我也在想,当存在堆损坏时可能会抛出它,我仍然在寻找它在代码库中的位置。

但我的问题是,除了内存不足或堆损坏之外,是否还有其他原因导致std :: bad_alloc被抛出? 我在Linux上使用GNU g ++。

最有可能的是,你真的没有记忆。 这将是一个非常罕见的堆损坏错误,一直导致抛出bad_alloc。 这就像手术精确的涂鸦一样。

代码中只有一个错误可能会分配大量内存。 但是你会期望在这个代码中抛出异常,至少是很长一段时间。 异常来自许多不同的地方的事实与此相反。

严重的碎片可能会导致问题,特别是对于malloc实现较差的平台。 这种情况很少见,但确实发生了。

我立即做的一件事 - 捕获异常并调用保存/proc/self/maps副本的函数。 这将使您了解该过程的峰值内存使用情况。 您可以判断它是否接近任何平台,策略或硬件限制。

在linux上,当前的地址空间限制可用于人为地限制进程可以使用的内存量。 您可以使用setrlimit(RLIMIT_AS, ...)手动设置它。 这也可以使用ulimit -vbashrc为整个shell设置。 这也可以在/etc/security/limits.conf为整个系统设置。 这个地方甚至可能有一个/ proc / sys条目,我不确定。

如果达到地址空间限制,则在尝试分配更多内存时,您的进程将抛出std :: bad_alloc。 在64位系统上,这可以是一个很好的“安全”,以确保错误的应用程序或库不会因可用内存而耗尽,并使系统完全交换或停止工作。 确保程序没有在某个地方设置它,并确保环境的其余部分也没有设置它。 您可以在程序中间的某个位置插入一些代码来调用getrlimit(RLIMIT_AS, ...)以确保它没有在某个地方偷偷摸摸。

一个或许更常见的原因(当然,除了实际耗尽内存之外)是无符号整数环绕情况,其中uin32_t或uint64_t用于分配内存但是为0并从中减去1,导致非常大请求分配(64位,即数千PB)。

在任何情况下,跟踪此问题的最佳方法是使用GDB。 如果您的应用程序根本不使用异常(因此根本没有“catch”语句),那么您可以启用核心文件( ulimit -c unlimited )。 下次程序崩溃时,操作系统将生成一个核心文件,并在GDB中加载它会立即给你一个回溯,显示程序崩溃的位置。

如果你有一些(但不是很多)使用try的地方并捕获这些错误的alloc,除了在你调试这个问题时将它们注释掉,你可以在GDB中运行应用程序并使用catch throw命令来获取GDB每次抛出异常时都会中断。 要使其中任何一个工作,请永远不要使用-fomit-frame-pointer编译,并始终使用-ggdb进行编译(即使使用-O3 )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM