Memory Management (II)
Memory Management (II)
Object Counting
"Object counting" is one technique for avoiding
memory leaks
When the program starts, initialize the object count
to zero
Every time an object is constructed, increment the
object count
Every time an object is destructed, decrement the
object count
Just before the program terminates, verify that the
object count is zero
int objectCount = 0;
class A {
Object Counting
public:
A() { ++objectCount; … }
~A() { --objectCount; … }
…
};
class B {
public:
B() { ++objectCount; … }
~B() { --objectCount; … }
…
};
void main() {
…
cout << "Object Count: " << objectCount << endl;
}
Object Counting
Adding code to manage the object count to every
class is tedious
It is convenient to put this code in a base class from
which other classes may inherit this functionality
class ObjectCount {
private:
static int creations;
static int deletions;
public:
ObjectCount() { ++creations; }
~ObjectCount() { ++deletions; }
static int GetCreations() { return creations; }
static int GetDeletions() { return deletions; }
static int GetObjectCount() { return creations-deletions; }
…
};
#include "ObjectCount.h"
Object Counting
class A : public ObjectCount {
public:
A() { … }
~A() { … }
…
};
void main() {
…
cout << "Object Count: " <<
ObjectCount::GetObjectCount() <<
endl;
}
Object Counting
If the object count isn't zero at the end of the program,
how do we fix it?
To figure out where the leak is, we need to know what
kinds of objects aren't being freed
The ObjectCount class tells us that there's a memory
leak, but it doesn't help us figure out which objects are
being leaked
ObjectCount only keeps a single global counter
void main() {
…
if (ObjectCountBase::GetGlobalObjectCount() != 0) {
cout << "A: " << ObjectCount<A>::GetClassObjectCount() << endl;
cout << "B: " << ObjectCount<B>::GetClassObjectCount() << endl;
}
}
Resource Management
Memory isn't the only kind of resource that must be
carefully managed
Other kinds of resources that can be allocated and
freed include:
Files
Network connections
GUI resources - windows, widgets, fonts, cursors, etc.
Database connections
These resources are allocated and freed using OS
system calls
Any of them can be leaked if they aren't properly
freed
Error Conditions & Resource Leaks
Resource leaks are especially likely when errors occur
Your code should ensure that dynamically-allocated
resources are ALWAYS freed, not just when
everything goes well
void DoStuff() {
auto_ptr<Widget> w = new Widget();
w->DoSomething();
w->DoSomethingElse();
cout << *w << endl;
}
No memory leak. The smart pointer
automatically deletes the object when it goes
out of scope
Smart Pointers
Notice that we are able to use the -> and * operators
on our smart pointer, just like with regular pointers
void DoStuff() {
auto_ptr<Widget> w = new Widget();
w->DoSomething();
w->DoSomethingElse();
cout << *w << endl;
}
void DoStuff() {
Widget * w = new Widget();
w->AddRef();
w->DoSomething();
Manually managing reference
DoSomethingElse(w); counts is extremely error-prone
if (w->ReleaseRef() == 0) {
delete w;
}
}
Reference Counting Utilities
Rather than managing reference counts manually,
use the Reference smart pointer class
#include "Referencable.h"
#include "Reference.h"
void DoStuff() {
Reference<Widget> w = new Widget();
w->DoSomething();
DoSomethingElse(w); The Reference constructor
} automtically calls AddRef