我正在開發一個內存泄漏的庫。該庫是一個基於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