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.
Publications
Anthony Allevato and Stephen H. Edwards. Dereferee: Instrumenting C++ pointers with meaningful runtime diagnostics. Poster presented at the 39th SIGCSE Technical Symposium on Computer Science Education, Portland, OR, 2008. dereferee-poster.pdf
Anthony Allevato and Stephen H. Edwards. Dereferee: Exploring pointer mismanagement in student code. In Proceedings of the 40th SIGCSE Technical Symposium on Computer Science Education. ACM Press, New York, NY, 2009. dereferee-sigcse09.pdf
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 withnew[]
ordelete[]
on memory allocated withnew
) - 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 SourceForge Project.
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, we require 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_platform: gcc under Mac OS X
- gcc_bfd_platform: gcc under any platform that supports the BFD library and the
/proc
filesystem (Cygwin and various Linuxes) - msvc_win32_platform: Microsoft Visual C++ 2005 under Windows
When building the Dereferee library, choose the appropriate platform for your platform. (See “BUILDING DEREFEREE” below.)
New platforms can be supported by writing a platform 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.
Contents
This kit is structured in the following manner:
demo/
– A small program used to demonstrate Derefereeinclude/
– Header files required for client code to use Derefereelisteners/
– A set of pre-written listener modules that interface with Derefereeplatforms/
– A set of pre-written platform modules that interface with Derefereesrc/
– The Dereferee library source codetests/
– A set of unit tests that can be used to verify Dereferee proper behavior on various platforms
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 targetslistener
: compile a listener module into an object file, specified by theLISTENER
variableplatform
: compile a platform module into an object file, specified by thePLATFORM
variablelibs
: compile the Dereferee library source and link it into a static library. You can specify aLISTENER
andPLATFORM
variables on the command line to pre-link specific listener and platform modules into the library. If any of these variables are left undefined, then the GNU makefiles will omit the listener and/or platform from the library and you will need to link these later; the Visual C++ makefiles will includemsvc_win32_platform
and/ormsvc_debugger_listener
by defaulttests
: compile the test suite and link it into arun-tests
executable (do not use theLISTENER
orPLATFORM
variables here; the test runner provides its own)demo
: compile the demo and link it into arun-demo
executable (theLISTENER
andPLATFORM
variables apply 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. The PLATFORM
variable is likewise the name of a platform 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 PLATFORM=gcc_macosx_platform LISTENER=stdio_listener
This will generate libdereferee.a
in the Dereferee/build
directory. For Microsoft Visual C++, you can run
nmake /F Makefile.mak libs PLATFORM=msvc_win32_platform LISTENER=msvc_debugger_listener
This will generate Dereferee.lib
in the Dereferee/build-msvc
directory. This library is compiled with the [/ M Dd](/MDd.html)
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 ofT*
when declaring pointers to heap memory in your code. This applies to variables, function arguments, and structure or class fields. Pointers to memory not allocated on the heap (such as stack memory) should remain asT*
; a runtime error will result if a checked pointer is assigned to memory that was not allocated on the heap.
Note: 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 following table shows the correct translations:
Original declaration | Dereferee declaration | |||
T* |
checked(T*) |
|||
const T* |
checked(const T*) |
|||
T* const |
checked(T* const) |
|||
const T* const |
checked(const T* const) |
In other words, checked
wraps the entire pointer type, including const
modifiers.
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.
Known Issues
- Dereferee only monitors pointers to memory allocated with the C++
new
ornew[]
operator. An attempt to set a checked pointer to point to any other memory (such as stack space or otherwise dynamically allocated memory, for instancemalloc
) will cause Dereferee to log an error at runtime. This behavior is currently by design and is unlikely to change. - There may still be one or two lingering issues with compilation ambiguities caused by the checked pointer template in more complex use cases. We have created what we believe to be a reasonably comprehensive suite of test cases to try to verify that all of the usual C++ constructs work with checked pointers substituted for raw pointers. However, it is possible that we have missed something. Any input from users with a great deal of expertise in esoteric C++ template constructs is always welcome.