Ruminations on Post Modern Programming
Saturday, September 30, 2006
  Plugins: Dynamically Loadable Classes
Both the philosophy of OOP and the virtual function mechanism of C++ make dynamic loadable classes or plugins easy. In fact, plugins are almost the ultimate proof of the power of the object oriented view of software.

The essence of polymorphism is swappable classes. One class can be used in place of another. This lets you change the details of a program, without changing the grand structure. This makes it easy to separate the problem domain, from the problem of the moment.

The problem domain changes very little. The problem of the moment can change quite often. Customer wants a new feature. Boss wants something done. If you have a box of tools that model the domain you are dealing with, then making these changes is like building something from Lego(tm) blocks. You just plug stuff together. If you don't have classes and functions appropriate to the domain you are dealing with, you are programming the same way cars were made before Henry Ford, before the assembly line, each car tediously built from scratch by master craftsmen.

For example, paying bills (the problem domain). Since Babylonia, the basic action of giving money to someone else hasn't changed in essence, even though the objects involved have changed. From barter, to gold nuggets, to horses, to daughters, to coins, to bank drafts, to credit cards to Paypal(tm). Money has represented the same thing, even though its form has changed. Your Pay() function only needs the general concept of money to function. It doesn't need to know or care about the particulars.

Plugins are classes that can be constructed at run-time instead of compiled into your program. Swappable classes can therefore be changed, without having to recompile your program. This is useful for reasons I will outline later.

Plugins are normally a real pain because each function you want to use must be "located" by symbol name before it is used. The old way to do it uses the C style functions GetProcAddress() for windows and dlsym() for Linux. You have to locate the function, get back a void* pointer and cast this pointer to the function involved, something like this:

typedef void (*TypeOfTheFunction)(int, const char*, long); // First you have to create a pointer
TheFunction* function = (TypeOfTheFunction) GetProcAddress("TheFunctionName", TheSharedLibrary);
if (function == NULL)
error;
Execute the function: TheFunction(1, “test value”, 2000);

This is tedious, error prone and inflexible. You have to write a locator function for each loaded function. You have to save that pointer for use later. All the code that calls that function must be aware it is a pointer and not a function. It's error prone because if you change a function in the library, but don't change the cast, your program will blow up. It's inflexible because you have to keep the library and your code constantly synchronized. The casts are hard coded and have to be recompiled if you change the library. Since C++ functions are garbled (decorated) you can’t even know the real function name anyway without a lot of paperwork.

However, with C++ you can do a neat little trick.

1) Define a base class, ideally, an abstract base class but not necessarily, in your program. All the functions you intend to be dynamic must be virtual functions.

2) Derive your plugin class from this base class.

3) Compile your plugin class into its own shared library (.dll for window, .so for linux) . See the example make file below on how to do this for Linux.

4) Export one function from your shared library that does a C++ new of your class object. That might be called "Create()" or something like that. This must be declared as extern “C”. The reasons are technical but the simple explanation is that the function name, unless declared extern “C” will be altered during compilation and you won’t know what the name is to look up when you use GetProcAddress() or dlsym().

5) Your class instance is created and returned to you but in the form of a base class pointer. Because the compiler knows about the base class functions, and your class has virtual versions of these, the program can use your class without having to have linked at compile time with your class. Even though the program thinks it is talking to the base class, the magic of virtual functions causes the functions in your plugin to be called. This means you don't have to manually locate all the function names and signatures in your loadable library and makes plugins via loadable libraries very easy to create.

Why would you want to do this?

1) You can change the classes your program uses by changing only a configuration file or command line option. No recompilation necessary and still type safe.

2) Users of your program can create their own plugins. Just provide them a skeleton of the abstract base class being used in your program and the header file of that abstract base class. When users create and contribute plugins it expands the glory of your original program for free.

3) You can load only those classes actually being used instead of an entire pantheon of code that only might be used.

4) This enables you to rapidly change your program's configuration so you can do comparative testing rapidly to see which plugins are better than others without recompiling. You can change major classes in your program without having to recompile.

5) Your program no longer needs massive functions full of "if" statements for each class of thing you are dealing with. For example, if you are converting text from a source format, to a destination format, the old style way of doing it would be to have a huge case statement where some output format is checked for and the proper output producer is called. This is inflexible. To add another format you have to change the “if” statements. Using plugins instead the user can specify an output plugin. Your program becomes infinitely configurable (without recompiling) in respect to output format.

6) Since your classes are not compiled in, there is no need to have a separate header and implementation file. The entire class declaration goes into the implementation file.

7) Once the plugin is created, any number of member functions is available without having to be explicitly looked up.

8) Plugin architecture prevents programmers from corrupting the core of your application. It forces them to do whatever needs to be done within the plugin, without altering the application and risking side effects caused by changing core features of your program. It enforces thinking in terms of encapsulation and polymorphism. That mental jump has not been made by too many programmers that I have met.

The reason this works without having to look up each function separately is the fact that the virtual function tables for the base and derived classes are in the same order. Virtual function number 1 is the same named function for both classes.

Here is the template class does most of the heavy lifting. The sample code works both on Linux and Windows.
---------- cut here -------------

#ifndef PLUG_IN
#define PLUG_IN

#include "string"
#ifdef _WIN32
#include "windows.h"
#else
#include "dlfcn.h"
#endif

// Anonymous namespace is here to keep linker from making this function (ErrorString) visible
// to the rest of your program. This is to prevent collision with some other library using the
// name ErrorString()
namespace
{
std::string ErrorString()
{
#ifdef _WIN32
return ::strerror(::GetLastError());
#else
return ::dlerror();
#endif
}
}

//ABSTRACT_BASE is the class that all the plugin we be being.
template class Plugin
{
std::string shared_library_filename_;
#ifdef _WIN32
HMODULE shared_library_handle_;
#else
void* shared_library_handle_;
#endif
typedef ABSTRACT_BASE* (*CreateFunction)(void);
CreateFunction create_function_pointer_;

void load()
{
#ifdef _WIN32
shared_library_handle_ = :: LoadLibrary(std::string(shared_library_filename_ + ".dll").c_str());
#else
shared_library_handle_ = ::dlopen(std::string(shared_library_filename_ + ".so").c_str(), RTLD_LAZY|RTLD_GLOBAL);
#endif
if (shared_library_handle_ == NULL)
throw std::string(std::string("Failed to load dynamic library ") + shared_library_filename_.c_str() +
"\nReason: " + ErrorString());
}

CreateFunction getSymbolAddress(const std::string &symbol)
{
if (shared_library_handle_ == NULL)
load();
#ifdef _WIN32
void* rval = ::GetProcAddress(shared_library_handle_, symbol.c_str());
#else
void* rval = ::dlsym(shared_library_handle_, symbol.c_str());
#endif
if (!rval)
throw std::string(std::string("Failed to find symbol ") + symbol + " in dynamic library "
+ shared_library_filename_ + "\nReason: " + ErrorString());

return (CreateFunction) rval;
}
public:
Plugin(const std::string &filename)
: shared_library_filename_(filename), shared_library_handle_(NULL), create_function_pointer_(NULL)
{
}

ABSTRACT_BASE* Create()
{
if (!create_function_pointer_)
create_function_pointer_ = getSymbolAddress("Create");

return create_function_pointer_();
}

~Plugin()
{
if (shared_library_handle_){
#ifdef _WIN32
::FreeLibrary(shared_library_handle_);
#else
::dlclose(shared_library_handle_);
#endif
}

create_function_pointer_ = NULL;
shared_library_handle_ = NULL;
}
};

#endif // endif PLUG_IN
---------- cut here -------------
#Linux Makefile
PLUGIN = Plugin1.so Plugin2.so
PROGS = PluginTest
INCLUDE = -I.
CPPFLAGS = -g $(INCLUDE)
LINKFLAGS = -L/lib -L/usr/lib -Wl,-rpath,.
CXX = g++
LIBS = -lreadline -lpcre
VERSION = 1

all: $(PROGS) $(PLUGIN)

$(PROGS): % : %.o
$(CXX) $(LINKFLAGS) $^ -o $@ $(LIBS)

%.o: %.cc Plugin.h
$(CXX) $(CPPFLAGS) -fPIC -o $@ -c $<

%.so: %.o
$(CXX) -shared -Wl,-soname,$@.$(VERSION) $< -o $@.$(VERSION).0 $(LIBS)
ln -f -s $@.$(VERSION).0 $@

clean:
-rm *.so
-rm *.o
-rm $(PROGS)
-rm $(PLUGIN)
---------- cut here -------------
// Abstract base class. For simplicity's sake, only has one function.
#ifndef PLUGIN_ABSTRACT
#define PLUGIN_ABSTRACT

class PluginAbstract {
public:
virtual const char *Value() const = 0;
};

#endif // endif PLUGIN_ABSTRACT
---------- cut here -------------
#include "pluginabstract.h"

class Plugin1: public PluginAbstract {
public:
virtual const char *Value() const {
return "Plugin1";
}
};

namespace {
extern "C"
{
#ifdef _WIN32
__declspec(dllexport)
#endif
Plugin1 *Create() { return new Plugin1; }
}
}
---------- cut here -------------
#include "pluginabstract.h"

class Plugin2: public PluginAbstract {
public:2
virtual const char *Value() const {
return "Plugin2";
}
};

namespace {
extern "C"
{
#ifdef _WIN32
__declspec(dllexport)
#endif
Plugin2 *Create() { return new Plugin2; }
}
}
---------- cut here -------------
#include "plugin.h"
#include "pluginabstract.h"

#include "iostream"

int main(int argc, char *argv[])
{
try {
Plugin plugin_factory(argv[1]);

PluginAbstract *plugin = plugin_factory.Create();

std::cout << Value()
}
catch(const std::string &e) {
std::cerr << e << std::endl;
return -1;
}
return 0;
}
 
Sunday, September 03, 2006
  Use C++ Exceptions Properly
Nomad: I am Nomad. I am perfect.
Kirk: I am the Kirk, the creator?
Nomad: You are the creator.
Kirk: You are wrong! Jackson Roy Kirk your creator is dead. You have mistaken me for him. You are in error. You did not discover your mistake. You have made two errors. You are flawed and imperfect and have not corrected by sterilization. You have made three errors.
Nomad: Error. Error. Error…..

Start Trek “The Changeling”

Let us hope that when Stardate 3541.9 rolls around, we will no longer be “in error”. For now, however, computer programs have lots of bugs. Bugs = wasted time, and thus wasted money. And I mean wasted money, millions and billions of dollars worth. Some famous computer catastrophes are available at http://encyclopedia.laborlawtalk.com/Computer_bug. My personal favorite being the flaw in the Mars Climate Orbiter software causing the loss of a space probe to Mars that cost 165 million dollars. I love the space program. We computer programmers can’t keep making this type of mistake and maintain credibility. As if we had any anyway. Many studies are showing that software projects are failing at an appalling rate http://www.it-cortex.com/Stat_Failure_Rate.htm

What I have found to be the biggest single reason for wasted time and money at coding time (design and specification failures are much more costly) is the failure to detect when the program erred. This means failure to check whether a function, the basic building block of every computer program, succeeded or not. The second most common problem is the failure to report an error when it does occur. And an outright crash is not the worse type of bug because that is reported to the user. Those happen and can be dealt with. It’s the invisible failures that stay in the program undetected that cripple your program for years before they are detected. Many of us have had the experience of going through some old legacy code and saying, “Oh my god! No wonder this never worked right! Look at this!!!”

Error detection, handling and correction are often never even thought of, and even in some of the biggest software houses are handled sloppily. The reason for this is not programmer laziness. It is because until recently programming languages did not have any consistent, enforceable methodology for dealing with the unexpected, with errors.

Debugging a computer program is a lot like accident reconstruction where the engineer tries to figure out why an airplane crashed. One has to trace back from effects to cause and this is time consuming. In computer programming we have the technology to trap errors almost the instant they begin, but almost no programmers do this. Why you ask? That is what I will be explaining in this article and telling you how to fix it.

To properly handle errors one must detect, report and handle them.

Detecting errors means, the computer program must be capable of changing its normal execution when something unexpected happens. This means every statement in a computer program that can potentially fail, must be capable of knowing it has failed.

Reporting errors means the computer program must make human beings aware that the error is happening, or has happened. Reporting does not have to immediately put up a message box demanding a human response. Sometimes the program is capable of working around the error, but it should log the error somewhere so that the situation can be remedied because errors that are worked around really mean the program is working in a semi-crippled manner.

I have found that the difficulty in finding and fixing bugs is always due to the lack of perceiving what is really going on in the computer. If the reason for the bug is visible to the programmer, fixing the bug is next to trivial. This is why it is critical to detect and report errors as soon as possible after they occur.

Handling errors means the program must be put back on the right track to continue performing its task. This is not always possible as some errors are catastrophic or fatal to the program, however, with a good operating system, language and compiler (such as Microsoft Visual C++) all errors, even hardware errors, can be detected, reported and handled, even if handling means to gracefully exit the program.

The above seems simple enough, so why isn’t it done more consistently? The fundamental reason is that legacy programmers who grew up using return codes are refusing to a large degree to move to using exceptions. I can’t explain for certain why but I suppose it’s the same reason they are using the old C language library functions (functions like strchr, strcat, etc) that are over 30 years old. I also worked with two Harvard Computer Science Graduates who avoided using exceptions like they were poison. I shudder to think that some greybeard professor bringing up the new generation of software developers wrongly instilled this into them. That the many “standard” libraries that come with every C++ computer also don’t use exceptions doesn’t help. I’m talking about the STL (Standard Template Library) and iostream library. For shame, how can these things be considered “standard” when they don’t even use the intended error handling features of the language.

There is a slight, ahem, degree of inertia involved in getting programmers to try new things. I am really tired of the prejudice against using exceptions and this article is an attempt to put a stake through the heart of this wicked beast who refuses to die in our modern programming world: error return codes. We need to be using exceptions, without exception.

Some smart people thought it wise to include exceptions in the C++ language, and after trying them for about a day I was sold. When a function fails its task, it invariably affects other parts of the program. Like a crowded freeway when one car stalls, the entire freeway jams up. When a function in a program fails, all the functions that depend on that function are also at risk. Once must recognize that when a function fails, the entire program enters a different state. We don’t just have an isolated failure. We have an entire new state of the program that might be called chaos because the unexpected has happened.

How to properly use C++ exceptions

I will assume you are familiar with C++ exceptions and have used them on occasion. If not, you might want to bone up on them: http://en.wikipedia.org/wiki/Exception_handling

What I’m going to show you is how to really revolutionize your programming by using exceptions to make error handling as painless as may ever be possible.

Exceptions will enable you to remove almost all error handling clutter from your code, make your code more easily re-useable and much easier to debug.

The exception mechanism is simple. Anywhere in your code where you want you can “throw”, like this:

throw “An error occurred here”;

or

throw 22;

or

throw std::string(“This is messed up right up in here.”);

You can “throw” any variable.

At other points in your program you “catch” anything thrown with the catch() statement which catches anything thrown from within the try area.

try
{
//do something
}
catch(std::string theException)
{
//if any exceptions are throw by “do something”, we come here
}

That’s it. That’s the simple syntax of using exceptions. Though the syntax is simple, how you use this is ultra powerful.

A simple example of how you might use exceptions:

FILE* FileOpen(const char* filename, const char* mode)
{
FILE* theFile = fopen(filename, mode);
if ( !theFile)
throw “Error opening file”;
return theFile;
}

int main(int argc, char* argv[])
{
try
{
FILE* theFile = FileOpen(“testfile.txt”, “r”);
// Do something with the file
}
catch(const char* error_string)
{
// If FileOpen fails we come immediately to here, skipping “Do something with the file”
puts(error_string);
exit(-1);
}
exit(0);
}

If FileOpen() fails, it throws an exception which immediately unravels all functions that were already called within try and executes the code contained in catch.

C++ provides you this syntax of exceptions. It doesn’t tell you how to use exceptions well. I’ll try to provide some help with that.

The first important rule to remember about using exceptions well is that (with one notable exception) you should only throw an exception when a function fails to perform its job. The reason for doing this is part and parcel of the philosophy for using exceptions and is embedded in the very name of the concept: exception. Exceptions should be thrown when the normal, expected flow of your program experiences an oddity, an exception. What is normally called an error falls into this category also.

The item thrown can be any class or anything that can be a variable. For the sake of simplicity, in the examples above I threw a const char*. For reasons I will get into later you normally want to throw a class specifically designed to be thrown. Why? Because error conditions are a sort of problem domain unto themselves and a class specifically designed to capture information for that domain is best.

The single most important thing to remember about exceptions is the try/catch system is simply a way to return, to throw away, an arbitrary number of stack frames. This means throwing an exception is like a function return, but the return can span many functions deep and return anything you want.

This is powerful because now you do not have to add error handling code everywhere, only where you actually care about doing something with the error.

That is the simplest, most general and accurate statement that defines the purpose of C++ exceptions. Why would you want to do this?

To be able to throw away any amount of a program if something fails because when something fails all the things that depend on that thing also will fail. This implies that an entire chain of functions is at risk if any one of them fails. A chain is broken if any one of its links are broken. If a link breaks, the entire chain starting at the very first link must be thrown away and that failure must now be dealt with (in the catch clause).

To recognize that error conditions present their very own peculiar requirements and due to the importance of errors in computer programs they need their own syntax and mechanisms to handle them.

First, I recommend you never throw the standard exceptions provided in your library such as std::runtime_error. This is not because they are badly written. It is because they are too general, not written for your program. Let me explain.

Success in Object Oriented Programming is largely based upon creating and using good components. The exception class you use might possibly be the most important single class you’ll ever use in your programs so it’s really important that it be good, or at least, not initially flawed because a good class can be subclassed later to add features. You don’t want to use an exception class that has built in limitations and the standard exceptions have built in limitations, mainly, they are what they are and you can’t change them to suit your application. If you change them, they are not longer the standard exceptions!

You should create your own exception class subclassed from std::exception. (In fact there is a general principle here that you should never use the classes provided by someone else directly because they will inevitably be lacking in some feature you need later, but a more complete discussion on that subject I’ll have to put off for another day). For example, here is the simplest Exception class you can get away with that subclasses from std::exception

#include <exception>

class Exception: public std::exception
{
};

This is a bare minimum but covers your ass by enabling you to retrofit features later as you come to need them. You could use this in your program and add more features to it later as they become necessary.

Something more useful would add a message that could be displayed later when the Exception was caught. Displaying the message should be done with the what() function because if you are catching std::exception, which you should be, its what() function is virtual so that any class derived from std::exception that gets caught will use its what() due to the magic of virtual functions.

#include <exception>
#include <string>

class Exception: public std::exception
{
std::string Message;

public:
Exception(const std::string& message)
: Message(message)
{
}

const char* what()
{
return Message.c_str();
}

~Exception() throw() // Here only to please some compilers

{
}
};

And there are other good reasons why you need to use your own exception class. Notice, all of these things are optional. The power of your exception class depends only how much you choose to add.

Once you have this basic exception class you can proceed to using exceptions. This next section will cover common programming diseases and how exceptions cure them.

Problems caused by not using exceptions and how to fix them

Disease: Programmers pathologically ignore or forget to check return codes from functions and now there are hard to find bugs in the program.

Until exceptions were invented the popular way to indicate a function failure was to return an error code, but this method depended upon the caller checking for the error value. This was more often than not ignored and thus programs failed seconds or minutes later for apparently unknown reasons and debugging was very time consuming (i.e. expensive) because the symptom of the error occurred a long way from its cause and one had to be a detective to track down the problem. Using error codes there was no mandatory requirement for the caller to check the error code. The returner of an error code is really at the mercy of the caller to ensure the error is dealt with. Experience has taught that the vast majority of function calls are not checked for error status leaving a hidden point of failure in your program that is time consuming and costly to track down when it does fail. It isn’t the common errors that occur a lot that kill you; it’s the ones that occur randomly and are hard to reproduce that destroy your product.

If you signal an error, i.e. a failure of the function to perform its task, by throwing an exception, a programmer must deal with it. It cannot be ignored by accident.

Disease: A clean and beautiful algorithm code is made obscure by messy error handling code.

Until exceptions came along, programmers didn’t mind adding all kinds of if statements to their algorithms that had nothing to do with the algorithm itself; all kinds of “if (error) then (do this)” statements which themselves are a good source of bugs in a program. Checking error codes is onerous and fills nicely written functions with error checking code that contributes nothing to the primary purpose of the function. You’ve got a significant portion of the function dedicated to handling failures, when failures occur in an insignificant percentage of the time. That is, you’ve got perhaps 30% of your code (if you are truly checking each function call for success of failure) devoted to .001% or less of the actual run time of the function. Imagine you are walking down the street and every step you take, having to look down and see if your foot actually made it! This is insane. This is what error codes are doing. If statements are also murderous on the execution speed of the program because the processor must throw out of its pipeline any pre fetched execution path that wasn’t taken.

Users of exceptions know that the big negative of using if statements to check return codes is that you are wasting time even when things are going well. Exceptions make it so that you only spend time when things are going wrong. If your function calls functions that themselves throw exceptions for error handling, you don’t have to add any error handling code in most cases. Most of the time all you are doing is passing a failure back to a caller higher up the stack. If you are using exceptions, this is done automatically for you and you need to add no code at all. In practice, only a few high level functions actually need to catch exceptions. Functions inherit their error handling and most don’t need explicit error handling code. Unnecessary because you will find when throwing and catching exceptions, you only throw where the error actually happens and you only catch where you want to handle. This is almost always several functions away meaning all intermediate functions need no error handling at all. They inherit their error handling. Using the analogy of walking down the street, you only react if something out of the ordinary occurs: your foot hits something and throws an exception up to your knee. Your knee doesn’t know how to handle this so it doesn’t catch the exception but allows it to propagate to your spinal chord which, in the same vein, doesn’t know what do so allows the exception to propagate to your brain which DOES know what to do. So your brain catches the exception and deals with it and you don’t have to explicitly check each and ever step you take. You only get alerted if SOMETHING GOES WRONG, NOT IF SOMETHING GOES RIGHT. The only reason you have to add any throws at all is because you are talking to old fashioned operating system calls that return error codes which you have to translate into a throw exception in your more modern C++ code.

This problem of code intending to do one thing being cluttered with code doing other stuff is so annoying to programmers that an entire programming approach has been invented called Aspect Oriented Programming: http://en.wikipedia.org/wiki/Aspect_Oriented_Programming

Using exceptions is very effective in removing clutter from your functions as regards error handling code. You won’t need Aspect Oriented Programming to deal with this.

Disease: Indecision and disagreement about how to deal with errors in a program.

Old style C programmers rely on the tired, old and completely unworkable error code hack. The return code programmer tries to come up with a return value that makes sense (at the time) but whatever he picks won’t necessarily be the same that someone else decided to use in the rest of the project. Return code conventions are inconsistent. For example the Windows API has a wide variety of conflicting and inconsistent return codes to indicate error. Some functions return true, others return false, others return an error value, some return 0, some return NULL, some return HRESULTS. The UNIX C functions are not much better. Over the years programmers have just accepted the fact that things are this screwed up. This is not a minor issue. Many bugs can be traced to programmer confusion over return codes and a lot of programmer time is consumed having to constantly look up what the function return value means in the documentation. How many of you know what printf() returns to indicate error? mkdir()? chdir()? stat()?

Also realize the mental energy the programmer wastes by having to make a stupid, and what he knows is really a useless decision about what error code to return. When a programmer is limited to return values as error indicators he has a constant problem while coding. “Here is a place that could fail. What do I do? Return -1? Return NULL? Return 0? Return an error value? Return false? Try to recover? How do I clean up what I already had in progress? Damn, now where was I? What was my function doing?

Ok now I’m using a function someone else wrote. What error does this function return? Should I check it or just hope for the best? Didn’t I just go through this same thought process the last function I wrote? Why doesn’t someone do something to fix all this wasted time and energy I spend every time I write a function?”

Exception-using programmers gracefully handle errors using exceptions. They simply throw Exception when their function cannot fulfill its task. They don’t have to ponder how the caller will handle this. A program or library that uses exceptions based upon std::exception is instantly future error compatible with other code using the standard exceptions so he doesn’t have to spend 50% of his brainpower trying to figure out what to do during errors which are .001% of the instances of his function being called.

You will also get programmers on a team fighting about this kind of stuff. That’s bad. Having a standard exception class makes it easier to reach a consensus because exceptions DO work for handling error conditions so you can reliably order them to do so and be confident your decision will work out in the end.

Disease: The functions cannot provide enough information about an error in order to decide how to handle it.

Return codes report next to nothing about errors. Error reporting done from error codes is next to useless as far as informing us what the error is. Error codes can only be a single number and thus can only display pre-canned system messages such as “no access” or “parameter failed” when in reality the error should report much, much more such as “Unable to open file foo.bar due to permission errors, it is not owned by you” or “Parameter 5 passed to function foo() was 27 which is out of the allowed range for this parameter”. Return code programmers stay late at work trying to figure out what happened. They don’t believe things should be easy and simple. Code has to be complicated to be good.

Exception users give full and accurate information about their errors. Exceptions can be any type of object and can report any information necessary. A nice, well rounded exception message might contain information like this: Windows Error(10045) Connection Timeout connecting to www.testpatch.com at location TCPConnect.cpp line 245 which gives you instantly what would take an “error code” programmer a half hour to gather. How much is your time worth? How much money does your organization have to hire programmers because your current programmers are wasting time tracking down reasons for errors and looking up error code numbers to see what human readable reason there is for the error to have happened? Isn’t the entire purpose of computers to save human beings labor? Successful programmers don’t waste time figuring out what happened. They have the computer tell them whenever possible. That’s what it’s there for.

Disease: An error occurs in a function that cannot return a value.

Some functions cannot return error codes. Constructors, conversion operators, and operator overload functions cannot return a success or fail value and thus cannot report a failure using error codes. Functions that return useful values such as the product of a multiplication cannot return an error value.

Old fashioned programmers who write buggy code handle failed constructors by having the constructed object mark itself bad by perhaps a bool Bad data member. Then check it later and not use it. This is really bad because, if an essential object fails to construct, the entire function which uses it must certainly also fail. There is no reason to continue past a failed constructor but since he isn’t using exceptions, the old fashioned programmer must now add all kinds of if (object-bad) garbage, often bigger in size than the code of the constructor itself, to handle its failure. He must also manually deconstruct anything that was constructed in this constructor and do all the accounting necessary to keep track of what was constructed and what wasn’t.

Using exceptions you simply throw if the constructor fails. Let the code that attempted to construct this object worry about what to do. C++ will automatically destruct any half constructed object for you.

Disease: Return codes corrupt the meaning of the word “function” and destroy the code’s usability as a function

Mathematically speaking, the definition of a function is this: http http://en.wikipedia.org/wiki/Function_%28mathematics%29. It’s important to note that a function translates multiple inputs into exactly one output. This means that the “result” of the function is the output, or in computer science, the return value. Why is this important? Because it implies that instead of having a static “value”, you can put in its place a “function()” which is dynamic and changing.

For example, you can print someone’s name:

Print “Jim Johnson”

Or you can print a transformation of the name more suitable to your needs.

Print LastNameOnly(“Jim Johnson”)

The latter line uses a function which, while being handled like a piece of data, actually computes a changing, dynamic value. The real power of the computer comes when doing many things with the same basic pattern, but slightly different details. That’s what functions can do for you. However, functions can fail. They may be unable to compute a return value for whatever reason. Programmers who only understand return codes, destroy the utility of a function by returning a “success” or “failure” indicator instead of the actual product of the function, in this case, just the person’s last name.

So if all you had available to deal with errors was returning a “special” value meaning “failure” the above simple code would become something like this (Here the programmer outputs the result into a variable he has already declared and uses the return value of the function as a success or failure indicator).

String LastName;
bool success = LastNameOnly(“Jim Johnson”, &LastName);
if (success)
Print LastName;
else
DealWithError()

Wow. You’ve gone from one line of code, to 6, effectively sextupling the complexity, bug probability and learning time for this code. This may not seem like much but if you multiply it by the thousands of functions in program it becomes quite significant. Instead of a statement, you now a program snippet that is not understandable at a glance. 5/6 of that snippet is devoted to error handling for a situation that might only occur 1 out of a million times in actual practice (person not having a last name). You are asking every programmer who ever reads this to spend 5/6 of his brain power thinking about something that might happen .00001 percent of the time. What the hell is so complicated about computing a person’s last name? Programmers whose relative importances are skewed will tell you “it’s very complicated. Why, in some cases, someone might not have a last name!”. I’m sorry, it isn’t, and 5/6 of a function shouldn’t be dedicated to problems that rarely occur.

If you return an error code instead of a useful value, you cannot use that function to replace data and your code becomes much more complicated, error prone and hard to learn.

A failing function is really akin to attempting to divide by zero. A failing function was fed something that it wasn’t prepared to handle, like attempting to divide by zero. So what’s a function to do? It cannot return a valid value, yet it must return something. Or must it? The answer is, throw an exception. This LastNameOnly() function will be part of some larger program. There will be many areas where there will be something wrong with the person’s name, or their account balance, or whatever. ALL will have the same result: we can’t do any calculations on this person. So you only have to catch those exceptions at one place, and the catch clause would probably be something that logged the problem and resumed execution on the next person.

Disease: Errors are occurring in the program but where to look in tens of thousands of lines of code?

How an old fashioned, non exception using programmer would handle this: He tries to guess what is happening and places breakpoints at the places that he suspects problems are happening. How much time and money do you want to waste on programmers guessing where to put breakpoints? There is no single place, object or module where errors get handled. This means there is no single place the programmer can inspect, log, measure, set breakpoints or display errors.

If you use a hierarchy of exceptions to signal errors, you know exactly where, when and how errors are occurring in your program at all times. How? Because all errors in your program call the base exception class constructor and there you can log, display, measure and set breakpoints. In my experience, this is in fact the first benefit most programmers notice when they start to use exceptions and one way to convince them to keep using exceptions. It is also a reason why you never want to use exceptions for trivial reasons. Doing so would make a constructor breakpoint like this break too often to be useful.

Disease: Errors are occurring in the program out on customers’ computers off site.

Old fashioned programmers who don’t use exceptions tell their boss: “I can’t debug this unless I can put the code in a debugger to see what’s happening”. Error messages are missing or so incomplete that the user cannot fix the situation nor can the programmer even understand what is going on remotely.

Users of a full featured exception class use full information in their errors so that often the error messages are descriptive enough for the user to fix his problem. Also, since all errors channel through the same function, the base exception class constructor, you can tell the user having a problem to turn on the logging and save a trace of the errors occurring offsite or even have the code send log messages across The Internet immediately so you can figure out exactly what is failing!

Disease: Some code is moved to another project and needs to be integrated into its error handling scheme.

Return coders know this project will be a nightmare. If the new environment doesn’t use the same conventions they did to do error handling, there will be a lot of rewriting, debugging, testing, crashes and customer frustration to deal with. Error codes cause the caller and the callee to have to agree upon a particular set of conventions, error codes, which makes both inflexible for use in other situations.

Using exceptions based upon the same standard subclass, std::exception, makes transferring libraries, classes and programs to other project completely error compatible. Even if the moved-to project uses a different exception hierarchy, catch clauses are all that have to be changed, and they are usually very few in most programs.

Disease: Hardware errors throw exceptions. Access violations, divide by zero, stack overflow and other usually fatal conditions are signaled by exception throws in many operating systems. If you aren’t prepared to deal with exceptions, all your program can do is die suddenly.

If you are depending on return codes to handle these, too bad. You’re screwed. Operating system will throw up an error message box and exit the program. Imagine a heart monitor program Access Violating and simply FAILING without at least notifying the nurse on call that something is wrong. Tsk tsk. Shame on you Mr. Return Code programmer.

Hardware errors are exceptions that can be caught just like any others. In Unix style OSs you use a signal handler, and in Windows you use _set_se_translator() to catch hardware exceptions and turn them into C++ exceptions. Then you can actually do something useful like print a stack trace to help debug or ring an alarm to ask a human being to come and help. In many cases if a thread has a hardware error you can catch it without crashing the entire program. In all cases you can catch the hardware error and deal with it in your own way instead of letting your operating system terminate the program.

Disease: The need to signal an error condition in code that has no provision for dealing with errors because when it was written no one expected that an error could occur here.

If you stuck using return codes there is little you can do except rewrite all the functions involved. Perhaps you can log the error and/or put up a message box informing the user. Forget about doing anything to actually handle the error. Retrofitting good error handling with return codes on already written programs is next to impossible. When the failing function is 10 levels deep and all the functions above it already have their return values being used for other things because the original programmers didn’t expect anything to fail, there is no way to return that error condition up the stack to someone who can do something about it. In the real world, the programmer just gives up and hopes the error doesn’t occur. Of course it does, it fails silently and the program behaves strangely and it takes days to track down what is going wrong with it.

Disease: Error conditions have no consistent schemes for dealing with them.

Exceptions give error handling its own set of tools more suited to the conditions error handling has to deal with. Code that uses exceptions has its own domain especially designed for handling errors. Retrofitting a new error condition on a program that uses exceptions to report errors involves very little new coding: just throwing the exception somewhere, and catching it somewhere else. And often it is not even necessary to write a new catch clause because an existing one already does the job. The point is, all you do is throw. The handling of the error is up to the higher level code which he can look at later.

Disease: Functions tangled with return code checking, propagate their problems to anyone else using them, spreading complexity like a cancer.

If the members of your class know how to copy themselves, then your class doesn’t need a custom copy constructor. The same is true for many other common functions like constructors, destructors, operator=, operator== etc. However, if any of those classes don’t use exceptions to signal failures, you cannot rely on these auto-generated functions and you must write custom versions. A real example from my last job was a situation where a class had a “File” member. In my class’s constructor initialization list that File class was constructed like this File(“datafile.txt”). However, this File object’s constructor was failing INVISIBLY because it did not use exceptions to signal a failure (it depended on the programmer to check a “good” variable). It took us hours to track down what the problem was. This is a clear example of why you should not rely on return codes even in classes that you consider trivial. The programmer’s excuse in this example was “that’s how the iostream library works”. The iostream library, bless its heart, was written before exceptions were part of the language. I suggest if you use it, wrapping it in your own classes that do throw exceptions if failures occur. It’s hard to get people to use exceptions if parts of the standard library do not, but that doesn’t mean they are correct. They aren’t exempt from the problems I describe above but their current state, the state of all “standard” c++ libraries reflects the battle we have going on between old fashioned programmers who refuse to use exceptions, and those who have seen the light and do.
A good starting exception class

Here is a rich but simple exception class that I recommend you start using as soon as possible.

#include <exception>
#include <string>
#include <cerrno>

// This STRINGIZE mumbo jumbo is necessary to turn __LINE__ into a string using only macro syntax
#define STRINGIZE(S) REALLY_STRINGIZE(S)
#define REALLY_STRINGIZE(S) #S

// The ErrorLocation() macro will turn into the file and line where it is used, like myfile:234
#define ErrorLocation() (__FILE__ ":" STRINGIZE(__LINE__))

class Exception: public std::exception
{
int SystemError;
int ApplicationError;
std::string Location;
std::string Message;
mutable std::string What;

public:
Exception(const std::string& message, const std::string& location = "", int systemError = 0, int applicationError = 0)
: Message(message), Location(location), SystemError(systemError), ApplicationError(applicationError)
{
// If the caller doesn't set the error, derive it from the last error the system is aware of
if (systemError == 0)
systemError = errno;
}

const char* what()
{
char errorString[1024] = "Unknown";

// If strerror fails, errorString will remain set to "Unknown"
strncpy(errorString, strerror(SystemError), sizeof(errorString));

What = "What: " + Message + "\n" +
// Only display system error system if there was one (non-zero)
(SystemError > 0 ? std::string("Why: ") + errorString + "\n" : "") +
// Only display location if we had set it in the constructor
(Location.empty() ? "" : std::string("Where: ") + Location + "\n");

return What.c_str();

}


~Exception() throw()
{
}
};


For simplicity’s sake I did not add certain things like access functions to get the Location and Message if those are the only ones you might want to display. You can add those easily enough if they become necessary.

Though not essential, there are many features you can easily add to an exception class to make it very useful for error handling. Here is a simplified version of the Exception class I use.

The what function is there so if you catch(const std::exception& ex) calling ex.what() will show the more complete error information in class Exception.

Then you can actually throw an exception like this:

FILE* file = fopen(“20th_Century_French_Battle_Victories.txt”);
If (!file)
throw Exception(“20th_Century_French_Battle_Victories.txt”, ErrorLocation());

Now, when you catch that exception, and use the what() function, the error string will be something very complete like:

What: 20th_Centry_French_Battle_Victories.txt
Why: File does not exist
Where: FindFiles.cpp:244

This saves you minutes looking up error codes etc. and helps not break your concentration while debugging, all in a few lines of code.

Now that you have a good exception class, how do you use it?

The most important thing about using exceptions is to be very clear about what an exception is. If you want your code to make the jump to light speed you can’t go halfway with exceptions. A lot of programmers are stuck between the old and new paradigms. I hear this quite often and it’s a problem, “Exceptions are for fatal errors but I still use return codes for some things”. This is not going to work. A very simple and clear criteria for using exceptions is, throw an exception when a function fails to perform its function. This means, no more error code returns at all, none, nada, zilch.

When I bring this up with some programmers I use the fopen() argument. If you have a function that opens a file, should it return a valid file handle if it succeeds, and NULL if it fails? If you said return NULL you aren’t getting what I’m saying. If your program is depending on the file to open and it fails, that’s the exact situation that requires an exception.

A failure to perform its task IS fatal for that function. You cannot know ahead of time how serious a failure of your function will be to the program using it. Exceptions were invented to fix problems with error handling. If you don’t use them you are stuck with the same old problems.

You need to use this definition of Exception, “An exception occurs when a function cannot accomplish its expected task”.
C++ Deficiencies

Compared to some languages, C++ provides only very basic exception capabilities, however the capabilities it does provide allow you to build almost all the advanced capabilities other languages include by default in their exceptions. One thing that is difficult to add for C++ exceptions is a stack trace. This is because there is no standard for stack traces in the language. You must add your own and this is problematic because different compilers and different processors treat the stack very differently.

In later articles I will show you how to add stack traces to your exceptions but that is beyond the scope of this article.

Bad ways to use exceptions

I’ve seen a lot of strange code in my day from programmers who weren’t really sure how to use exceptions. Once you understand that exception throwing is simply a way to return up the stack an arbitrary distance, everything else falls into place. Here are some examples of how NOT to use exceptions:

Bad Use: Never throw and catch an exception in the same function.

Exceptions exist as a new and revolutionary way to signal function failures. But some programmers are using them to create a “cleanup” routine at the end of a function. Throwing and catching in the same function is a sure sign of improper exception use. It means you haven’t gotten the idea that a failed function, fails by throwing an exception that is caught by someone else.

FILE* afunction(void) //VERY WRONG and just plain redundant
{
File* file = fopen(“afile.txt”, “r”);
try
{
if (!file)
throw Exception(“Could not open file”);
}
catch(Exception& e)
{
return NULL;
}
return file;
};

This is really silly. And all permutations of this type of thing are silly also. Because they are simply returning an error code anyway or catching the exception and dealing with it, meaning, the function did not fail, it was able to handle the situation. Never throw and catch an exception in the same function! Exceptions should be used to signal a failed function. If you use exceptions for trivial conditions that aren’t function failures you will end up increasing the clutter in your code. If your function fails, throw an exception, don’t catch it and translate back into the bad old return code habit. The above function should be written like this if you insist on using return codes:

FILE* afunction(void) // Bad, old fashion but at least not a corrupted use of exceptions
{
File* file = fopen(“afile.txt”, “r”);9
return file;
};

Bad Use: Don’t “half-use” exceptions

Many programmers, and even the standard library, have the idea that exceptions should be reserved for “fatal” errors only. They still use old style return codes in many functions. There is a huge flaw in the logic of this approach. A failure to perform its function is fatal to the function involved. Only the catcher of an exception can know if the exception is fatal to the program or not. You cannot possibly predict 100% how your class will be used. If your class has any success at all it will be reused in ways you never imagined. If you use an exception class based on std::exception you will not limit future users of your class.

For short utility programs, dying if an exception is thrown no big deal, but the bigger or longer running a program is, the more likely errors must be recoverable. If you are writing pacemaker software, every error must be recoverable. However, the fatality of the exception isn’t decided by the thrower, it’s decided by the catcher of the exception. If you are programming a library of code that is intended to be re-used (and why aren’t you?) it isn’t up to you to decide how an error in your library will affect the program using it? Use exceptions and let the user decide.

Bad Use: catch(…)

Normally you never want to use catch(...). This catches ALL exceptions but you cannot know what type of exception was caught or any information about that exception. Often programmers say to themselves “oh well, if anything happens here I don’t care, just ignore it”. This is not in itself a problem but as code grows, that original code being try/catch protected might grow and often you will need to know what’s going on and cannot simply suppress errors. There is also this factor: when you ship a product it’s better that it continue to run and recover wherever possible. Users are very critical of obvious crashes and might not even notice subtle errors so

One solution is to catch(…) in shipping code so your users see fewer of your warts and perhaps the program can limp along still functional, however, during development you never want to suppress errors. Using a macro for catch(…) will do the trick:

#ifdef _DEBUG
#define CATCHALL catch(const Exception& e)
#else
#define CATCHALL catch(…)
#endif

Bad Use: Not having exception safe functions

When you program using exceptions there is one slight change you have to make in your style. Your code must be written so that it can handle an exception being thrown any time your function calls any other function that might throw an exception. When an exception gets thrown your function will be exited immediately at that point. Any local variables will be destructed just as in a normal return. Remember, an exception occurring is basically just a return occurring as far as your programming approach. This is actually very easily done by simply declaring certain variables using auto_ptr which is part of the C++ standard library. I will write an article dedicated to this in the future but you can research that yourself if you demand immediate satisfaction.

An unusual but appropriate use of exceptions

If you have ever programmed using multi-threading you have come across the problem of “how do I properly stop a thread that is running?”. You cannot just stop the thread by killing it, you must somehow make the thread return to its starting point so that all intervening resources it was using are cleaned up. If you just kill the thread using the operating system facilities you can leave memory leaks, open files, unreleased mutexes and all sorts of nasty messes.

The solution to this is to somehow make your thread throw a special exception, not derived from std::exception because you don’t want it caught by any normal error code. You only catch it in your thread’s opening function before you did anything significant that might need cleanup. I will write another article on this at another time.

Walt Howard

 
Programming design, tips, pitfalls and stories from the front lines of software developmnet.

Name:
Location: Lake Arrowhead, California
ARCHIVES
September 2006 /


Powered by Blogger