2013-01-22 51 views
0

我正在C++中开发贝叶斯推理采样器,它在树上中继很多,并且这个树是在智能指针(Boost的shared_ptr和weak_ptr)的帮助下实现的。Boost shared_ptr不会立即销毁对象

在推断过程中(即运行一个长时间的C++函数1-2分钟),树被改变很多,创建并销毁了许多节点。

完全推理过程(100%负载)占用处理器(更精确地说,它是一个线程)。出于某种原因,新内存(对于新节点)正在被占用,但旧内存不会被完全释放,这会在内存溢出1-2分钟后导致内存溢出。

虽然,如果我在推理过程中添加暂停,程序似乎完全销毁旧对象,并且一切正常。

在我看来,原因是析构函数(或者更准确地说,它后面发生的事情,即内存释放)由于某种原因而被延迟。

请问:请问: 1)这看起来是一个真正的问题吗? 2)如果是,那么等待“足够的内存”被释放时如何更好?什么是标准策略?

(该程序正在被在Unix上运行。)

+3

对我来说,听起来像你的shared_ptr仍然有引用持有给他们,因此不会被直接销毁。但说实话,很难说没有任何代码。 –

+1

'shared_ptr'只是调用'delete'。你确定观察到的行为不是由于“删除”?因为'删除'实现是已知的,它推迟了实际的处理,假设他们可以回收分配。 – MSalters

+0

MSalters,你可以给出一个关于删除实现的信息,并推迟释放吗?我认为这可能是我的情况。 (对不起,还没有找到我自己。) –

回答

0

当指向对象的最后的shared_ptr被破坏,该对象被立即删除。所以你听起来很奇怪。我能想象的唯一想法就是你已经为你的实现附加了一个垃圾收集器......否则,请检查所有旧对象是否被破坏。

2

您观察到的内存问题似乎并不位于C++本身。如果shared_ptr释放它的内存,它会立即执行,而不是以某种延迟的方式。但是,您认为合适的操作系统可能会延迟“真正”版本一段时间。像Windows的“任务管理器”这样的程序看起来好像程序消耗的内存越来越多,而这只是操作系统为您预留的内存,但实际上并不占用您的内存。如果你的计算产生了如此巨大的处理器负载,那么调度器可能会延迟相当“不重要”的任务(如释放内存),直到有时间,以免妨碍计算等更重要的事情。

但是,释放和分配内存很昂贵。而且你似乎可以自由分配大量的内存。你应该考虑通过做自己的内存管理(比如内存池等),或者通过回收对象(即节点)本身来回收那些内存,这意味着不会真的销毁它们,而是将它们还给一些“节点池”并用新的值重新设置它们。两者都可以与shared_ptr结合使用。

+0

谢谢!请问,如果不使用内存池概念,是否有任何方法可以(1)控制调度程序的优先级,以执行取消分配作为第一优先级,(2)或者如果不可能调整调度程序,有多合理并优雅地暂停等待必要的释放? –

1

声音就像你在树中有循环一样,即它对子和父指针都使用shared_ptr,这可以防止自动树节点的破坏。使用普通指针可能会更好。

+2

或者使用一个方向的强指针和另一个方向的弱指针。或者在删除对象时手动断开指针。 –

+0

@DavidSchwartz虽然它不比简单的指针更简单。 –

+0

通常不需要跟踪删除对象的安全时间就可以了。用我的两种方法,你不需要。 –