メモリリークを解消したい
Posted: 2013年7月06日(土) 23:20
様々な型を一つのリストに格納できる双方向リストを作りたいと思い、下記のコードを書きました。現在、push()とget()でメモリリークが発生しており、自分では原因がわからず困っています。よろしくお願いします。
検証コード:
/*=================================================================
new / delete時にメモリ計測を行うクラス
=================================================================*/
class mem_base {
public:
//---------------------------------------------------------------
// コンストラクタ
//---------------------------------------------------------------
mem_base();
//---------------------------------------------------------------
// メモリ確保
//---------------------------------------------------------------
void *operator new(size_t t);
void *operator new[](size_t t);
//---------------------------------------------------------------
// メモリ解放
//---------------------------------------------------------------
void operator delete(void *p);
void operator delete[](void *p);
}; // end class mem_base
/*===================================================================
自作型名前空間
===================================================================*/
namespace type {
/*=================================================================
双方向循環list:
要素を追加する際に型を指定することで異なる型をリストにできる
=================================================================*/
class list : public mem_base {
protected:
/*---------------------------------------------------------------
listを構成する最小要素
---------------------------------------------------------------*/
class cell_base : public mem_base {
public:
cell_base *next;
cell_base *prev;
cell_base() : next(NULL), prev(NULL), mem_base() {}
}; // end class cell
/*---------------------------------------------------------------
listのデータ部
---------------------------------------------------------------*/
template <class U> class cell final : public cell_base {
public:
U data;
cell() : cell_base(){}
};
/*
リストの先端
*/
mem<cell<tchar> > head;
public:
/*---------------------------------------------------------------
コンストラクタ
---------------------------------------------------------------*/
list() : mem_base(), head(mem<cell<tchar> >())
{
// 循環リストを作成
head.get().prev = head.get().next =
&static_cast<cell_base&>(head.get());
}
/*---------------------------------------------------------------
後端にpush
---------------------------------------------------------------*/
template<class U> void push(const U &n) {
cell<U> *c = new cell<U>;
c->data = n;
c->prev = head.get().prev;
c->next = &static_cast<cell_base&>(head.get());
c->next->prev = c->prev->next = c;
}
/*---------------------------------------------------------------
指定位置をpop
---------------------------------------------------------------*/
void pop(cell_base *p) {
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
}
/*---------------------------------------------------------------
リストの先頭を返す
---------------------------------------------------------------*/
const cell_base *begin() const { return &(cell_base&)head.get(); }
cell_base *begin() { return &(cell_base&)head.get(); }
/*---------------------------------------------------------------
デストラクタ
---------------------------------------------------------------*/
~list(){
auto a = begin();
while(a != a->next) {
pop(a->next);
}
}
/*---------------------------------------------------------------
値を取得する
---------------------------------------------------------------*/
template<class U> void get(
const type::list::cell_base *p,
U &t
){
/*
constを外してダウンキャストしたポインタを左辺値へ格納する
*/
type::list::cell<U> *a =
static_cast<type::list::cell<U>*>(
const_cast<type::list::cell_base*>(
p
)
);
t = a->data;
}
}; // end class list
} // end namespace type