[英]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.