
libmdc is a set of utility and debugging classes that I expect would be useful in most C++ programs. Mostly it consists of assertion bottlenecks to help you eliminate pointer and memory bugs from your programs. There will be more soon to help with class invariant and design by contract assertions. libmdc - Mike Crawford's C++ Library http://www.goingware.com/libmdc/ It's also meant to make unit testing easier. It includes CPPUnit.mk and CPPUnit.t.mk, sub-makefiles which ease building CPPUnit unit tests with GNU make. My assertion_failed exception class includes a macro which can be used by your own assertion macros to throw an exception upon assertion failure. This enables one to use CPPUnit to test assertion failures without aborting the tests. My mdc_assert can do this. libmdc is Free Software, released under the Boost Software License. It's my intention that when I'm finished writing it, I will submit it for review for possible inclusion in Boost itself. It is not nearly done yet, but this preview release is provided to solicit comments. My question for you is, do you see any obvious mistakes? How can I do better? My valid_ptr template is a non-owning smart pointer that cannot be NULL. I'm also going to write a template I'll call checked_ptr that CAN be NULL. valid_ptr uses and checked_ptr will use the legal_addr template which reads the first byte addressed by any reference or non-NULL pointer. Given an unmapped address, it causes an immediate crash, but probably sooner and easier to debug than letting it snowball through your program. Used with a memory debugger like valgrind, Purify or Spotlight, you can find and fix bad memory references with ease. I have used this technique before and while it's dead-simple, it is also very powerful. libmdc doesn't have proper documentation yet, but there is some in the form of comments in the header files. The unit tests also serve as sample code. The Makefile is extensively commented to show you how to use CPPUnit.mk to build unit tests for your classes. CPPUnit.mk itself contains complete documentation for its use. I build unit tests the way John Lakos advises in Large Scale C++ Software Design: I only link in the class under direct test, and those sources which are absolutely required to make the test link. For reasons that Lakos eloquently explains, I DON'T link in my entire project, as I think is the more common practice. To keep this manageable, I need a separate makefile to build each unit test. CPPUnit.t.mk encapsulates what is common to building all unit tests, so that the *.t.mk unit test makefiles need have little more in them than a list of the dependencies. Following is from the README file: libmdc is a set of utility and debugging classes likely to be useful in many C++ projects. Everything is in the namespace mdc. There aren't any dependencies on anything outside this directory except for the standard C++ library, Boost and CPPUnit for the unit tests. You will need to build and install the Boost C++ library and the CPPUnit automated test framework before you can build this code: http://www.boost.org/ http://cppunit.sourceforge.net/cppunit-wiki/ To build the executables, just take "make". To build and then run the tests (both unit tests and other tests) type "make test". There is no "make install" yet. The library so far contains: CPPUnit.mk, CPPUnit.t.mk Sub-makefiles to make it a lot easier to build CPPUnit unit tests with GNU make. valid_ptr non-owning smart pointer; forbids NULL pointers. legal_addr pointer debugging, best used with valgrind, purify or spotlight. null_ptr_checker throws an exception when given a NULL pointer. null_ptr_exception The exception it throws. mdc_assert Debugging macro, aborts or drops into debugger when its assertion evaluates to false. This is used instead of the standard library assert so it may be separately disabled. Assertions are enabled by default, for release builds, #define MDC_NO_ASSERT 1 or pass -DMDC_NO_ASSERT=1 to the C++ compiler. assertion_failed meant for testing failed assertions in unit tests. You can configure mdc_assert to throw this exception with #define MDC_ASSERTION_EXCEPTION 1 errno_exception on POSIX systems, throw this exception after a system call fails so that the catcher can print a good error message string_invariant The beginning of class invariant assertions for the Standard Library valid_ptr is a smart pointer like auto_ptr, scoped_ptr or shared_ptr, except that it doesn't take ownership of the pointer it holds. Instead, construct a valid_ptr from a pointer that your class or function is given to use, but not manage. It will throw a null_ptr_exception and optionally assert if the pointer is ever NULL. Besides validating the pointer it is given, valid_ptrs serve as documentation to help make ownership issues clear. Using valid_ptrs as class member variables indicates that the pointers are used by, but not owned by the class. Similarly, declaring them as function parameters indicates that the pointers passed in cannot be NULL, and again that ownership of them is not captured by the receiving function. Use either scoped_ptr, shared_ptr or auto_ptr for situations where pointer ownership is required. Which one to use depends on the requirements of each situation. There is sample code too: the tests. There are unit tests for most of the classes that use the CPPUnit automated test framework. There is also a simple program called HeaderCheck that I used to debug some problems with my header files while I was first writing valid_ptr.h. CPPUnit does some extreme macro and template magic, so HeaderCheck serves as a simpler testbed. Enjoy! -- Mike -- Michael D. Crawford GoingWare Inc. - Expert Software Development and Consulting http://www.goingware.com/ crawford@goingware.com Tilting at Windmills for a Better Tomorrow.