Bur*_*rad 7 c++ linux heap g++ exception
我正在研究相当大的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, ...)。也可以在中bashrc使用设置整个外壳ulimit -v。也可以在中为整个系统进行设置/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并捕获这些不良分配的地方,而不仅仅是在调试此问题时将其注释掉,则可以在GDB中运行该应用程序,并使用catch throw命令让GDB中断每个引发异常。为了使它们中的任何一个都起作用,请不要使用进行编译,也不要-fomit-frame-pointer始终使用进行编译(即使使用-O3)-ggdb。