我正在开发一个内存泄漏的库。该库是一个基于boost :: asio构建的数据流服务。服务器端使用堆内存管理系统,该系统提供内存以保存有限数量的samples
,同时等待通过tcp连接进行推送。当第一次构建服务器时,将为所有旧的sample
分配一堆内存。从这个堆中,在穿过套接字传递一个sample
之后,内存将返回到堆中。避免内存泄漏造成的新(新[])
这很好,除非所有预先分配的堆已被占用。下面是创建一个“样本”的功能:
sample_p new_sample(double timestamp, bool pushthrough) {
sample *result = pop_freelist();
if (!result){
result = new(new char[sample_size_]) sample(fmt_, num_chans_, this);
}
return sample_p(result);
}
sample_p
只是模板到sample
类typedef定义智能指针。
违规行在中间。当freelist
上没有一块内存时,我们需要做一些。这会泄漏内存。
我的问题是为什么会发生这种情况?由于我将新样本推送到智能指针中,因此当内存超出范围时它不应该释放内存(稍后它会从堆栈中弹出)。我是否需要以某种方式处理内部分配的内存 - 即。内存分配由new char[sample_size_]
?如果是的话,我该怎么做?
编辑: @RichardHodges这里是一个可编译的MCVE。这是非常简单的,但我认为它捕捉到我在原代码中遇到的问题。
#include <boost/intrusive_ptr.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <iostream>
typedef boost::intrusive_ptr<class sample> sample_p;
typedef boost::lockfree::spsc_queue<sample_p> buffer;
class sample {
public:
double data;
class factory{
public:
friend class sample;
sample_p new_sample(int size, double data) {
sample* result = new(new char[size]) sample(data);
return sample_p(result);
}
};
sample(double d) {
data = d;
}
void operator delete(void *x) {
delete[](char*)x;
}
/// Increment ref count.
friend void intrusive_ptr_add_ref(sample *s) {
}
/// Decrement ref count and reclaim if unreferenced.
friend void intrusive_ptr_release(sample *s) {
}
};
void push_sample(buffer &buff, const sample_p &samp) {
while (!buff.push(samp)) {
sample_p dummy;
buff.pop(dummy);
}
}
int main(void){
buffer buff(1);
sample::factory factory_;
for (int i = 0; i < 10; i++)
push_sample(buff, factory_.new_sample(100,0.0));
std::cout << "press any key to exit" << std::endl;
char foo;
std::cin >> foo;
return 0;
}
当我逐句通过代码时,我注意到我的delete操作符永远不会被样本指针调用。我猜想我正在处理的库(我再也没有写过,因此我仍然在学习它的方法)错误地使用了intrusive_ptr类型。
你没有显示智能指针类型... –
这看起来像是地狱。你能发布一个编译的MCVE吗? –
@RichardHodges星期一来。 – dmedine