Dereferee is a C++ template library intended for introductory C++ students learning about manual memory management and pointers. It provides a pointer template class that is instrumented to give highly detailed diagnostics about memory leaks, pointer-related errors that would normally cause a program crash, and other unwise behavior that may not cause an immediate failure but lead to one further down the line.
Unlike other pointer templates, such as std::auto_ptr and Boost's wide array of pointer templates, Dereferee's checked pointer does not to any memory management of its own--it will not fix problems, but merely report them so that the student can fix them on his or her own.
A journal paper describing Dereferee is currently in progress. This poster (TODO: Update link to permanent location) describing the toolkit was presented during a poster session at SIGCSE 2008.
Features
Dereferee detects and logs the following kinds of errors or other poor programming practices:
Calling the incorrect version of delete (that is, delete on an array allocated with new[] or delete[] on memory allocated with new)
- Deleting or dereferencing an uninitialized pointer
- Deleting or dereferencing memory that has already been freed
- Dereferencing a null pointer
- Memory leaks caused by the last valid pointer to a live block of memory going out of scope or being overwritten
- Performing a comparison with a pointer that has been deleted, is out of scope, or is uninitialized
Using the array index operator on a pointer that was not allocated using new[]
Referencing an array index that is outside the bounds used when allocating the array with new[]
- Invalid use of pointer arithmetic
Dereferee can also optionally pad the ends of allocated memory blocks with "safety bytes" that are checked upon deletion to determine if bad pointer usage has caused any buffer underflows/overflows.
By default, the Dereferee memory manager will output at the end of execution a block of summary test that includes the size and location of any leaked memory blocks, as well as statistics about the number of calls made to new/delete and the amounts of memory used during execution.
Download
The Dereferee toolkit can be downloaded here from our SourceForgeProject.
This ZIP file contains the Dereferee source code, makefiles to support building a link library on a variety of platforms, a small demo application, and a comprehensive set of unit tests to ensure the consistency of Dereferee's diagnostics.
Requirements
Dereferee requires a C++ compiler with a very high level of standards-compliance, due to significant use of features like partial template specializations. Dereferee is currently known to work under the following compilers and platforms:
- gcc 3.4 (Cygwin)
- gcc 4.0+ (Mac OS X, Linux)
- Microsoft Visual C++ 2005
Furthermore, to support determining the source file location of errors that occur at runtime, Dereferee requires that it be possible to collect a backtrace at runtime and examine the symbol table of an executable. Pre-written modules have been written to support the following platforms:
gcc_macosx_listener: gcc under Mac OS X
gcc_bfd_listener: gcc under any platform that supports the BFD library and the /proc filesystem (Cygwin and various flavors of Linux)
msvc_win32_listener: Microsoft Visual C++ 2005 under Windows
When building the Dereferee library (see below), choose the appropriate listener module for your platform.
New platforms can be supported by writing a listener module that provides the appropriate lower-level functionality for that platform. New listeners can also be written to customize the manner by which Dereferee outputs its diagnostic messages.
A future version of Dereferee is likely to refactor these listeners into two separate components--one to handle the low-level aspects such as symbol table access and backtrace collection, and another to manage the output of the diagnostic messages.
Building Dereferee
You can use Dereferee either by including its source tree directly in the build process of your project, or separately compile it into a static library that can be linked into your project.
The Dereferee kit contains GNU makefiles for Cygwin, Mac OS X, and Unix platforms, and nmake makefiles for Visual C++. The makefile targets are as follows:
all: build all of the following targets
listeners: compile all of the listeners into separate object files
libs: compile the Dereferee library source and link it into a static library. You can specify a LISTENER variable on the command line to pre-link one of the listener modules into the library. If this variable is left undefined, then the GNU makefiles will omit the listener from the library; the Visual C++ makefiles will include msvc_win32_listener by default
tests: compile the test suite and link it into a run-tests executable (do not use the LISTENER variable here; the test runner provides its own)
demo: compile the demo and link it into a run-demo executable (the LISTENER variable applies here as well)
The value of the LISTENER variable described above is the name of the listener module object file, without a path or extension.
You can also use the run-tests and run-demo targets to automatically run the respective executable after it has been built.
For example, to build libdereferee.a on Mac OS X, you can run
make libs LISTENER=gcc_macosx_listener
This will generate libdereferee.a in the Dereferee/build directory. For Microsoft Visual C++, you can run
nmake /F Makefile.mak libs LISTENER=msvc_win32_listener
This will generate Dereferee.lib in the Dereferee/build-msvc directory. This library is compiled with the /MDd option to use the multithreaded debug DLL version of the Visual C++ C runtime library.
Usage
To use Dereferee in your own code, you must first prepare your project:
Place the Dereferee/include directory in your project's include path.
Include <dereferee.h> in any source or header file that will declare or use checked pointers.
- Link to the Dereferee static library (or include the source code for the library in your build process). Likewise, if you have not already linked a listener module object file into the static library itself, link to it as well.
Use checked(T*) in lieu of T* when declaring pointers to heap memory in your code. This applies to variables, function arguments, and structure or class fields.
Notes:
Pointers to memory not allocated on the heap (such as stack memory) should remain as T*; a runtime error will result if a checked pointer is assigned to memory that was not allocated on the heap.
Since in C++, the declaration const T* means "a pointer to a const object of type T," the analogous Dereferee declaration is checked(const T*), not const checked(T*).
The main design goal of the Dereferee toolkit is transparency; since this code was designed to be used by students who are just learning C++, it was highly desirable to make the functionality as unobtrusive as possible. Through C++ templates, operator overloading, and a minimal set of preprocessor macros, the Dereferee kit provides the checked(T*) syntax that can be used almost anywhere that a standard C++ heap pointer could be used. Only the declaration of the pointer need change; almost any other usage of the pointer (including calls to new/delete) will work as expected without modification.