2011-11-09 55 views
5

我正在研究一個相當大的SIP電話應用程序,偶爾當我們使用集成Web UI(使用tntnet編寫)在沉重的通話負載下時,程序將退出,原因是std: :引發bad_alloc。有數百個正在使用的線程(每個活動調用3個),因此導致異常的代碼的位置非常隨機,但始終在使用GUI之後。引發std :: bad_alloc的其他可能原因

現在,我明白std :: bad_alloc可以在內存不足時拋出,在這種情況下情況並非如此。我也在想,當存在堆腐敗時它可能被拋出,我仍然在尋找它可能存在於代碼庫中的哪個地方。

但我的問題是,除了內存不足或堆損壞之外,是否還有其他原因會引發std :: bad_alloc?我在Linux上使用GNU g ++。

+0

自定義分配器在使用中? – sehe

+0

不是我所知道的,或見過的。 –

+0

僅當分配內存失敗時引發bad_alloc,不過正如您所注意的那樣,如果您的程序執行了任何未定義的操作,則可能會執行任何操作,包括在未定義的操作之後隨時拋出bad_alloc –

回答

5

很可能,你真的是內存不足。這將是一個非常罕見的堆腐敗錯誤,始終導致只有 bad_alloc被拋出。那就像塗手術一樣精準。

這是可能的只是在代碼中分配大量內存的錯誤。但是你會希望在那個代碼中拋出異常,至少是很大一部分時間。這個例外來自許多不同的地方的事實與此相反。

嚴重的碎片會導致問題,特別是對於實施不佳的平臺malloc。這很少見,但確實發生了。

我會立即做一件事 - 捕捉異常並調用一個保存/proc/self/maps副本的函數。這會給你一個關於該進程的高峯內存使用情況的好主意。您可以判斷它是否在任何平臺,策略或硬件限制附近。

3

在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的地方,它捕獲這些不良分配,除了在你調試這個問題的時候註釋它們外,你可以在GDB中運行應用程序並使用catch throw命令每次拋出異常時都讓GDB中斷。對於其中的任何一種工作,請勿使用進行編譯,並始終使用-ggdb進行編譯(即使使用-O3)。

相關問題