Skip to content

Commit

Permalink
Tracked: More resilient leaked object reporting.
Browse files Browse the repository at this point in the history
darcs-hash:20070828203724-ec8c9-a2ad4f892db913e6519f652236385deb401f7bbd.gz
  • Loading branch information
Eelis committed Aug 28, 2007
1 parent 586506b commit be35e9e
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 30 deletions.
20 changes: 10 additions & 10 deletions prelude/tracked.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ namespace tracked
{
namespace detail
{
unsigned int Idd::new_id = 0;
id_t Idd::new_id = 0;

Idd::Idd (): id(new_id++), pillaged(false)
Idd::Idd (name_t const name): id(new_id++), name(name), pillaged(false)
{
reg.s.insert(this);
reg.s.insert(std::make_pair(id, name));
for (Allocations::iterator i = allocations.begin(); i != allocations.end(); ++i)
if (i->first.first <= this && this < i->first.second) { i->second.insert(id); break; }
}

Idd::Idd (Idd const & i): id(new_id++), pillaged(false)
{ i.nopillage("copy"); reg.s.insert(this); }
Idd::Idd (Idd const & i, name_t const name): id(new_id++), name(name), pillaged(false)
{ i.nopillage("copy"); reg.s.insert(std::make_pair(id, name)); }

Idd & Idd::operator= (Idd const & i)
{ i.nopillage("assign from"); pillaged = false; return *this; }
Expand All @@ -32,21 +32,21 @@ namespace tracked
void Idd::nopillage (char const * const s) const
{
if (!pillaged) return;
std::cout << " Error: Tried to " << s << " pillaged " << name() << id << '.';
std::cout << " Error: Tried to " << s << " pillaged " << name << id << '.';
silent_exit();
}

#ifdef __GXX_EXPERIMENTAL_CXX0X__

Idd::Idd (Idd && i): id(new_id++), pillaged(false)
{ i.nopillage("move"); i.pillaged = true; reg.s.insert(this); }
Idd::Idd (Idd && i, name_t const name): id(new_id++), name(name), pillaged(false)
{ i.nopillage("move"); i.pillaged = true; reg.s.insert(std::make_pair(id, name)); }

Idd & Idd::operator= (Idd && i)
{ i.nopillage("move-assign from"); pillaged = false; i.pillaged = true; return *this; }

#endif

Idd::~Idd () { reg.s.erase(this); }
Idd::~Idd () { reg.s.erase(id); }

Allocations allocations;

Expand All @@ -56,7 +56,7 @@ namespace tracked
{
if (s.empty()) return;
std::cout << " || leaked:";
BOOST_FOREACH(Idd const * const b, s) std::cout << ' ' << b->name() << b->id;
BOOST_FOREACH(map::value_type const & p, s) std::cout << ' ' << p.second << p.first;
}
}
}
55 changes: 35 additions & 20 deletions prelude/tracked.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,63 @@ namespace tracked
{
namespace detail
{
typedef char name_t;

struct Idd
{
Idd ();
Idd (Idd const &);
Idd & operator= (Idd const &);

#ifdef __GXX_EXPERIMENTAL_CXX0X__
Idd (Idd &&);
Idd & operator= (Idd &&);
#endif
typedef unsigned int id_t;

virtual ~Idd ();
unsigned int const id;
id_t const id;
name_t const name;

protected:

Idd (name_t);
Idd (Idd const &, name_t);

Idd & operator= (Idd const &);

#ifdef __GXX_EXPERIMENTAL_CXX0X__
Idd (Idd &&, name_t);
Idd & operator= (Idd &&);
#endif

virtual ~Idd ();

void nopillage (char const *) const;

private:

bool pillaged;

virtual char name () const = 0;
static id_t new_id;

static unsigned int new_id;
static struct Reg { std::set<Idd const *> s; ~Reg (); } reg;
struct Reg
{
typedef std::map<id_t, name_t> map;
// This used to be a std::set<Idd const *>, but that broke when ~Reg tried to print the name and id of an Idd that was leaked and yet no longer around (for instance because it was placement-new'd into a stack-allocated buffer).
map s;
~Reg ();
};

static Reg reg;
};

void silent_exit ();

typedef std::map<std::pair<void const *, void const *>, std::set<unsigned int> > Allocations;
extern Allocations allocations;

template <typename Base, char Name>
template <typename Base, name_t Name>
struct T: Base
{
T () { std::cout << ' ' << *this << "* "; }
explicit T (name_t const name = Name): Base(name) { std::cout << ' ' << *this << "* "; }

explicit T (int const i) { std::cout << ' ' << *this << "*(" << i << ") "; }
explicit T (int const i, name_t const name = Name):
Base(name) { std::cout << ' ' << *this << "*(" << i << ") "; }

T (T const & t): Base(t) { std::cout << ' ' << *this << "*(" << t << ") "; }
T (T const & t, name_t const name = Name):
Base(t, name) { std::cout << ' ' << *this << "*(" << t << ") "; }

T & operator= (T const & t)
{ Base::operator=(t); std::cout << ' ' << *this << '=' << t << ' '; return *this; }
Expand All @@ -63,7 +79,8 @@ namespace tracked

// Moves are displayed as =>, because -> and <= are operators.

T (T && t): Base(std::move(t)) { std::cout << ' ' << t << "=>" << *this << "* "; }
T (T && t, name_t const name = Name):
Base(std::move(t), name) { std::cout << ' ' << t << "=>" << *this << "* "; }

T & operator= (T && t)
{ Base::operator=(std::move(t)); std::cout << ' ' << t << "=>" << *this << ' '; return *this; }
Expand Down Expand Up @@ -129,8 +146,6 @@ namespace tracked
allocations.erase(i);
::operator delete(p);
}

char name () const { return Name; }
};

template <typename B, char N>
Expand Down

0 comments on commit be35e9e

Please sign in to comment.