2009-12-26 73 views
2

我有一個緩衝類在我的C++應用程序如下:的std ::矢量儲備方法無法分配足夠的內存

class Buffer 
{ 
    public: 
    Buffer(size_t res): _rpos(0), _wpos(0) 
    { 
     _storage.reserve(res); 
    } 

    protected: 
    size_t _rpos, _wpos; 
    std::vector<uint8> _storage; 
} 

有時使用構造失敗,因爲它無法分配所需的存儲空間。例如,有一次,調用構造函數與res = 37造成以下堆棧跟蹤,我從它的核心轉儲有一個段錯誤:

#0 0x00007f916a176ed5 in raise() from /lib/libc.so.6 
No symbol table info available. 
#1 0x00007f916a1783f3 in abort() from /lib/libc.so.6 
No symbol table info available. 
#2 0x00007f916a1b33a8 in ??() from /lib/libc.so.6 
No symbol table info available. 
#3 0x00007f916a1b8948 in ??() from /lib/libc.so.6 
No symbol table info available. 
#4 0x00007f916a1bb17c in ??() from /lib/libc.so.6 
No symbol table info available. 
#5 0x00007f916a1bca78 in malloc() from /lib/libc.so.6 
No symbol table info available. 
#6 0x00007f916ac0c16d in operator new (sz=37) 
    at ../../.././libstdc++-v3/libsupc++/new_op.cc:52 
     p = <value optimized out> 
#7 0x00000000004e3d11 in std::vector<unsigned char, std::allocator<unsigned char> >::reserve (this=0x7f911bc49cc0, __n=31077) 
    at /usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/ext/new_allocator.h:89 
     __old_size = 0 
     __tmp = <value optimized out> 

我編譯使用GCC 4.4.2作爲64位應用程序和該應用程序我在Debian 5 x64中使用它。

任何幫助,非常感謝。 謝謝

+0

跟蹤定義顯示res = 31077,而不是您聲稱的37。它仍然很小(至少對於64位系統),但是你可能在錯誤的地方尋找錯誤。你能從回溯中看到8幀以上的幀嗎? – Tomek 2009-12-26 13:09:39

回答

2

如果你不能使用Valgrind找出你的內存由於它意味着沉重的負載而損壞的位置,你仍然可以用更輕的解決方案進行測試。

對於Valgrind不適用的服務器應用程序(因爲該平臺在Solaris 8上),我用mpatrol(http://mpatrol.sf.net),但特別是dmalloc(http://dmalloc.com)的結果非常好。

在某種程度上,您可以在不重新編譯的情況下使用它們(僅爲dmalloc重新鏈接,用於mpatrol的庫預加載)。他們會替換內存原語來對內存使用進行額外檢查(對這些原語的錯誤爭論,逐個閱讀,堆損壞......)其中一些檢查將在發生問題時正好觸發,而其他檢查會比實際的錯誤代碼晚一點被觸發。通過調整啓用哪些檢查以及檢查頻率(如果適用),您可以在執行基本檢查時以幾乎全速運行。

我建議使用dmalloc重新編譯以獲得所謂的'FUNC_CHECK',對於我來說,這增加了很多錯誤識別的準確性,性能成本可以忽略不計。

8

由於segfault是在malloc中,所以很可能有其他代碼已經拋出堆(即寫入他們不擁有並正在被堆管理器使用的部分內存)。

我建議使用Valgrind來查找哪些代碼是垃圾堆。

+0

我無法使用Valgrind作爲這個應用程序,因爲它是一個服務器應用程序,並且負載很重。 Valgrind使其變得如此之慢以至於幾乎無用。因此,segfault不會發生。不幸的是,我需要Valgrind以外的解決方案來找到原因。也許我可以在應用程序中實現以找到原因。 – 2009-12-26 11:29:01

+1

@Martin York:如果你沒有注意到,我試圖通過讓其他人引導我發現我的錯誤來學習編寫沒有任何錯誤的代碼。 – 2009-12-26 21:21:36

+0

如果你沒有注意到,馬丁約克只是引導你找到你的錯誤。 ;) 在另一臺機器上運行valgrind。最終,你沒有很多選擇。 *在這個過程中的某個地方,某段代碼會以某種方式破壞堆*,並且會在發生此段錯誤之前的一段時間破壞堆。正如Martin York所說,您只有兩種選擇:1)編寫不包含這些錯誤的代碼,或者2)運行診斷工具*,例如Valgrind *以幫助您找到存在的錯誤。 – jalf 2009-12-27 02:38:17