2013-06-04 121 views
4

我有一組程序與共享內存(ipc)〜48GB一起工作。沒有valgrind的內存泄漏狩獵

程序在運行Linux 3.6.0-RC5,主計算機上的書面純C,編譯GCC 負載平均是6.0跳躍到16.0每10秒(24芯)從其他機器

一個代理接收數據通過0mq(3.2.3,來自同一網絡中12臺機器的〜1000 msgs/s),寫入共享內存 許多工作人員讀取這些數據並進行一些計算。

使用大約20%cpu的代理 每個使用1%CPU的工作人員定期跳過10%。

所有程序編寫時,所有分配中的init()完成這樣的方式 - 調用時程序啓動,全部免費做過的destroy() - 所謂退出前

重複的代碼不使用任何的malloc /釋放calloc /免費在所有。

但這兩個程序仍然泄漏。大約每分鐘120-240字節。這不是很多 - 在7-8天耗盡內存,我只是開始/停止過程,但那些泄漏的字節吃我的腦海每次監視應用程序報告我關於此重新啓動:)

壞事 - 我無法運行valgrind應用共享內存 - 它只是停止分配/連接共享內存,然後一切都開始崩潰。

試圖找到這個漏洞我已經做了剝離版本的代理 - 沒有泄漏,但我不能用相同數量的數據餵它。

當在gdb下運行時仍然沒有泄漏,但速度下降了2/3左右 - 所以可能是它沒有那麼快來重現這個錯誤。

所以可能泄漏是:

  • 我的代碼。但沒有malloc/calloc。只是指針+ - ,memcpy,memcmp
  • 一些標準庫。 glibc的?系統日誌?
  • 0mq與許多源工作(不要以爲每秒1K /封郵件太多流量)

是任何其他工具/庫/黑客存在,可在這樣的情況下幫助?

編輯:Shivan Raptor詢問代碼。重複部分是5k行數學。沒有我提到的任何分配。

但是啓動,停止和重複進入這裏:

int main(int argc, char **argv) 
{ 
    ida_init(argc, argv, PROXY); 
    ex_pollponies(); // repetive 
    ida_destroy(); 
    return(0); 
} 


// with some cuttings 

int ex_pollponies(void) 
{ 
    int i, rc; 
    unsigned char buf[90]; 
    uint64_t fos[ROLLINGBUFFERSIZE]; 
    uint64_t bhs[ROLLINGBUFFERSIZE]; 
    int bfcnt = 0; 

    uint64_t *fo; 
    uint64_t *bh; 

    while(1) { 
    rc = zmq_poll(ex_in->poll_items, ex_in->count, EX_POLL_TIMEOUT); 
    for (i=0; i < ex_in->count; i++) { 
     if (ex_in->poll_items[i].revents & ZMQ_POLLIN) { 

     if (zmq_recv(ex_in->poll_items[i].socket, &buf, max_size, 0) == 0) 
      continue; 
     fo = &fos[bfcnt]; 
     bh = &bhs[bfcnt]; 
     bfcnt++; 
     if (bfcnt >= ROLLINGBUFFERSIZE) 
      bfcnt = 0; 

     memcpy(fo, (void *)&buf[1], sizeof(FRAMEOBJECT)); 
     memcpy(bh, &buf[sizeof(FRAMEOBJECT)+1], sizeof(FRAMEHASH)); 

     // then store fo, bh into shared memory, with some adjusting and checkings 
     // storing every second around 1000 msgs 16 bytes each. But leaking is only 200 bytes per minute. 

     } 
    } 

    } 
} 

EDIT2:

我終於讓Valgrind的工作 - 只是做數據(6GB)的使用一部分,它終於過去了。並沒有發現任何泄漏。但是,在工作過程中,它需要100%的CPU,絕對是我的程序不處理所有傳入的數據 - 它不能滿負荷工作。 這一半證實了我的lasthope猜測 - 泄露是在數據交換塊。 我發現有關mtrace(libc的一部分)的信息 它幫助我跟蹤漏洞的地址 - 它在我的代碼之外,在一個線程中。我的代碼中唯一的線程是由zeromq創建的。然後我開始玩套接字(增加hwm,緩衝區)的選項和泄漏速度下降,但並沒有完全消失,即使在荒謬的大值:(

因此,現在我95%肯定它的zeromq泄漏。在

+1

你的代碼在哪裏? – Raptor

+0

查看您使用的庫函數的文檔。他們中的任何人是否爲你分配內存並期望你釋放它? – Shahbaz

+0

是什麼讓你覺得有泄漏?統計數據可能會引起誤解 - 例如如果您在初始化時分配內存,並且稍後再觸摸它,則僅在觸摸時分配頁面,這看起來像正在進行分配。 – ugoren

回答

3

他們的郵件列表的valgrind如果不解決這個問題 - 你可以嘗試自己跟蹤內存分配

有兩種方式 - 更換您的通話通過調用自己的malloc和free的版本對malloc,並通過在這些職能的某種標識,如FILELINE,也可以在通過第分配的系統的名稱。

在您通過直接malloc和free,並在內存泄漏檢測模式下,您第一次登錄的alloc和免費通話,然後通過調用malloc和free非內存泄漏檢測模式。當程序結束時,您將匹配分配和釋放,並且您會看到內存泄漏的位置。

你可以用宏做到這一點,所以你經常構建不會放緩。

你不會從你不能重新編譯自己的客戶端庫趕上泄漏。

另一種方法是在連接時使用gcc的-wrap標誌有GCC打電話給你的版本的malloc /自由,而不是glibc的一個。看到這個帖子:

Create a wrapper function for malloc and free in C

這樣做的好處是,你將能夠登錄分配在客戶端庫爲好。缺點是,你是有限的功能相同的簽名,所以你將無法得到FILELINE在泄漏檢查。

如果這是C++,你可以重載的全局operator new。