为什么会立即销毁共享指针泄漏内存?
这里有没有内存泄漏?为什么会立即销毁共享指针泄漏内存?
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
的来电!) 我的假设是,在第一次调用得到了一些记忆,然后因为我做什么用第二次调用的智能指针会立即删除它。简单?但是,当我运行我的程序时,内存会随着时间的推移而增加,跳跃。然而,当我在节目中唯一打电话给广播()时,它不会!
ps的输出为版本,而不broadcast()
:
%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,克++ 4.4,助推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超时意味着每个计时器都会以50次/秒的速度调用broadcast()
。我在我的函数开始时设置了到期时间,并在接近结束时运行计时器。被遗忘的代码并没有那么做;将调试信息输出到std :: cout可能是占用CPU最多的工作。我想有时可能会立即触发计时器;但是,我仍然不明白这会是一个问题,更不用说造成内存泄漏。
(该程序运行正常,顺便说一下,做了充分的任务即使;我只当我发现通过PS报告的内存使用量已经跳起来了疑惑。)
UPDATE:感谢答案和评论。我可以补充说,我将程序在每个系统上运行了几个小时,内存使用量没有再增加。 (当Centos版本第二次跳转时,我也准备将其视为一次性堆重组或其他东西)。无论如何,很高兴知道我对智能指针的理解仍然健全,并且存在没有我需要关心的线程的奇怪的角落案例。
如果有泄漏的消息,则分配一个std::string
(20字节,更多或更少的)50倍每秒。 在1小时内您应该已经分配... 3600 * 50 * 20 = 3,4MBytes。
您看到的与64K无关,这可能是由于系统将内存分配给进程的方式,即new
子分配给变量。
系统在删除某些内容时需要“垃圾回收”,将其重新放回可用内存链以供进一步分配。 但是,由于这需要时间,所以大部分系统都不会执行此操作,直到释放的内存超过了一定的数量,这样才能完成“重新打包”。
那么,这里发生的事情可能不是你的程序正在泄漏,但由于某种原因,系统内存分配器决定为你的应用程序保留另一个64 kB页面。如果在这一点上存在一个持续的内存泄漏,那么在50 Hz的速率下,这将会产生更为戏剧化的效果!我不知道(我不是那个领域的专家),但我猜想有一些启发式和统计数据涉及到了。我不知道(我不是这方面的专家)。或者,它可能仅仅是堆已经分散。
可能发生的另一件事是,你是保持在缓冲器变长随时间:)
1)您的代码示例不能编译。 2)在我[修复](http://ideone.com/FCPHf)之后,我将它运行在valgrind下。它不会泄漏。 – 2012-02-22 06:49:43
我怀疑你正在看到堆管理的效果,而不是泄漏(例如碎片等)。有时候堆管理器可能会给你一个新的内存块,而不是重复使用现有的内存管理器来考虑性能,而且这种行为是不确定的。如果你想真正检查这些东西,请使用调试分配器(MSVC++随附一个,对于GCC,你可以像Rob那样使用Valgrind) – 2012-02-22 07:06:39
如果你显示的代码是程序唯一的东西,它可能是一个问题。但是,您可能也在做其他许多事情,并且可以轻松解释其中的差异。 – 2012-02-22 07:09:43