Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 引发std::bad_alloc的其他可能原因_C++_Linux_Exception_G++_Heap - Fatal编程技术网

C++ 引发std::bad_alloc的其他可能原因

C++ 引发std::bad_alloc的其他可能原因,c++,linux,exception,g++,heap,C++,Linux,Exception,G++,Heap,我正在开发一个相当大的SIP电话应用程序,有时当我们在高呼叫负载下使用集成的web UI(使用tntnet编写)时,程序会因为抛出std::bad_alloc而退出。有数百个线程在使用中(每个活动调用3个),因此导致异常的代码的位置非常随机,但总是在使用GUI之后 现在,我知道std::bad_alloc在内存不足时会被抛出,但在这种情况下并非如此。我还认为它可以在出现堆损坏时抛出,我仍在寻找它在代码库中的位置 但我的问题是,除了内存不足或堆损坏之外,还会抛出std::bad_alloc吗?我正

我正在开发一个相当大的SIP电话应用程序,有时当我们在高呼叫负载下使用集成的web UI(使用tntnet编写)时,程序会因为抛出std::bad_alloc而退出。有数百个线程在使用中(每个活动调用3个),因此导致异常的代码的位置非常随机,但总是在使用GUI之后

现在,我知道std::bad_alloc在内存不足时会被抛出,但在这种情况下并非如此。我还认为它可以在出现堆损坏时抛出,我仍在寻找它在代码库中的位置


但我的问题是,除了内存不足或堆损坏之外,还会抛出std::bad_alloc吗?我正在Linux上使用GNU g++。

很可能,您的内存确实不足。这将是一个极为罕见的堆损坏错误,它始终只会导致抛出bad_alloc。那就像是用外科手术般精确地涂鸦

有可能只是代码中分配了大量内存的bug。但您可能希望在该代码中抛出异常,至少大部分时间是这样。这一例外情况来自多个不同的地方,这一事实与此相反

严重的碎片可能会导致问题,尤其是对于
malloc
实现较差的平台。这很少见,但确实发生过


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

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

如果达到地址空间限制,则在尝试分配更多内存时,进程将抛出std::bad_alloc。在64位系统上,这是一种很好的“安全”措施,可以确保坏的应用程序或库不会因可用内存而流失,并使系统切换或完全停止工作。确保程序没有在某个地方自行设置,并且确保环境的其他部分也没有设置。你可以在程序中间插入一些代码来调用<代码> GeTrimeLime[RimiTimas,…] <代码>,以确保它没有在某个地方偷走。

一个可能更常见的原因(当然不是实际内存不足)是无符号整数环绕情况,其中使用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
),我不知道也不曾见过。bad_alloc仅在分配内存失败时才会抛出,不过正如您所注意的,如果您的程序执行任何未定义的操作,它可能会执行任何操作,包括在未定义动作后的任何时间抛出bad_alloc