簡體   English   中英

為什么立即銷毀共享指針會泄漏內存?

[英]Why would an immediately destroyed shared pointer leak memory?

這里有內存泄漏嗎?

class myclass : public boost::enable_shared_from_this<myclass>{
//...
    void broadcast(const char *buf){
    broadcast(new std::string(buf));
    }

    void broadcast(std::string *buf){
    boost::shared_ptr<std::string> msg(buf);
    }
//...
};  

(這是仍然顯示問題的精簡版本 - 通常我在第二次broadcast呼叫中真正工作!)我的假設是第一次調用得到一些內存,然后因為我對智能指針什么都不做,第二次調用會立即刪除它。 簡單? 但是,當我運行程序時,內存會隨着時間的增長而增加。 然而,當我將該程序中唯一的調用注釋為broadcast()時,它沒有!

沒有broadcast()版本的ps輸出:

 %CPU  %MEM     VSZ    RSS  TIME
 3.2   0.0     158068  1988 0:00 
 3.3   0.0     158068  1988 0:25  (12 mins later)

調用broadcast() (在Ubuntu 10.04上,g ++ 4.4,boost 1.40)

 %CPU  %MEM     VSZ    RSS  TIME
 1.0    0.0    158068  1980 0:00
 3.3    0.0    158068  1988 0:04  (2 mins)
 3.4    0.0    223604  1996 0:06  (3.5 mins)
 3.3    0.0    223604  2000 0:09
 3.1    0.0    223604  2000 2:21  (82 mins)
 3.1    0.0    223604  2000 3:50  (120 mins)

(看到在3分鍾左右的跳躍在我迄今為止試過的幾次中是可重現的。)

調用broadcast() (在Centos 5.6上,g ++ 4.1,boost 1.41)

 %CPU  %MEM     VSZ    RSS  TIME
 0.0    0.0     51224  1744 0:00
 0.0    0.0     51224  1744 0:00  (30s)
 1.1    0.0    182296  1776 0:02  (3.5 mins)
 0.7    0.0    182296  1776 0:03
 0.7    0.0    182296  1776 0:09  (20 mins)
 0.7    0.0    247832  1788 0:14  (34 mins)
 0.7    0.0    247832  1788 0:17
 0.7    0.0    247832  1788 0:24  (55 mins)
 0.7    0.0    247832  1788 0:36  (71 mins)

以下是如何調用broadcast() (來自boost :: asio計時器),現在我想知道它是否重要:

void callback(){
//...
timer.expires_from_now(boost::posix_time::milliseconds(20));
//...
char buf[512];
sprintf(buf,"...");
broadcast(buf);
timer.async_wait(boost::bind(&myclass::callback, shared_from_this() ));
//...
}

(回調與廣播功能屬於同一類)

我有4個這樣的計時器,我的io_service.run()由3個線程池調用。 我的20ms超時意味着每個計時器調用broadcast() 50次/秒。 我在函數開始時設置了到期時間,並在接近結束時運行計時器。 遺漏的代碼並沒有做那么多; 將調試信息輸出到std :: cout可能是CPU占用最多的工作。 我想有時計時器有時會立即觸發; 但是,我仍然看不出這會是一個什么問題,更不用說造成內存泄漏了。

(順便說一下,程序運行正常,即使在執行完整任務時也是如此;當我注意到ps報告的內存使用率上升時,我才開始懷疑。)

更新:感謝您的回答和評論。 我可以補充一點,我讓程序在每個系統上運行了幾個小時,內存使用量沒有進一步增加。 (當Centos版本第二次跳躍時,我也准備將其視為一次性堆重組或其他東西。)無論如何,我很高興知道我對智能指針的理解仍然是合理的,並且有沒有奇怪的角落情況,我需要關注。

如果存在泄漏,則每秒50次分配std::string (20字節,或多或少)。 在1小時內你應該被分配... 3600 * 50 * 20 = 3,4MBytes。

您所看到的與64K無關,這可能是由於系統為進程分配內存, new子分配給變量的方式所致。

刪除某些內容后,系統需要“垃圾收集”,將其放回到可用的內存鏈中以進行進一步分配。 但是由於這會花費時間,所以大多數系統在釋放的內存超過一定數量之前不會執行此操作,以便可以進行“重新打包”。

那么,這里發生的可能不是你的程序泄漏,但由於某種原因,系統內存分配器決定為你的應用程序保留另一個64 kB的頁面。 如果此時存在持續的內存泄漏,以50 Hz的速率,則會產生更大的影響!

我不知道為什么會在3分鍾后完成該操作(我不是該領域的專家),但是我想其中涉及一些啟發式方法和統計信息。 或者,可能只是堆變得碎片化了。

可能發生的另一件事是,您保留在緩沖區中的消息會隨着時間的流逝而變長:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM