gpt4 book ai didi

c++ - 为什么立即销毁的共享指针会泄漏内存?

转载 作者:行者123 更新时间:2023-11-30 03:03:25 25 4
gpt4 key购买 nike

这里有内存泄漏吗?

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 个线程池调用。我的 20 毫秒超时意味着每个计时器调用 broadcast() 50 次/秒。我在我的函数开始时设置了到期时间,并在接近结束时运行计时器。省略的代码并没有做那么多;将调试信息输出到 std::cout 可能是最占用 CPU 的工作。我想有时计时器可能会立即触发;但是,我仍然看不出这会是个问题,更不用说导致内存泄漏了。

(顺便说一句,程序运行良好,即使在完成其全部任务时也是如此;只有当我注意到 ps 报告的内存使用量猛增时,我才开始怀疑。)

更新:感谢您的回答和评论。我可以补充一点,我让程序在每个系统上再运行几个小时,内存使用量没有进一步增加。 (当 Centos 版本第二次跳跃时,我也准备将其视为一次性堆重组或其他东西。)无论如何,很高兴知道我对智能指针的理解仍然是正确的,并且有没有我需要关注的带有线程的奇怪极端情况。

最佳答案

如果存在泄漏,您将每秒分配 50 次 std::string(20 个字节,或多或少)。在 1 小时内,您应该已经分配了 ... 3600*50*20 = 3,4MBytes。

与您看到的 64K 无关,这可能是由于系统将内存分配给进程的方式,即 new 子分配给变量。

系统在删除某些内容时需要对其进行“垃圾收集”,将其放回可用的内存链中以供进一步分配。但是由于这需要时间,所以大多数系统在释放的内存超过一定数量之前不会执行此操作,以便可以进行“重新打包”。

关于c++ - 为什么立即销毁的共享指针会泄漏内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9390222/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com