|
By Reg Charney
I am about to start a project in which I hope to use C++’s
exception handling mechanism. I say “hope” because writing
exception-safe code is not as simple as writing code that produces
invalid results if exceptions are thrown. The tradeoffs are between
writing clearer code that works predictably under almost all
circumstances but that may be slightly slower against code that may
be faster, but produces unpredictable results under stressful
conditions such as running out of resources.
Listing #1 shows a simple example that is not exception safe. See
if you can identify some of the problems. A more exception safe
version of this example is shown in the Listing #2.
class
Hdr { }; // assume variable header size
class Txt { }; // assume variable text body size
class Msg { // composite class
Hdr *pH;
Txt *pT;
public:
Msg() { pH = new Hdr; pT = Txt; }
Msg(const Msg& m)
{
pH = new Hdr(*m.pH);
pT = new Txt(*m.pT);
}
Msg& operator=(const Msg& m) //
assignment operator
{
delete pH;
delete pT;
pH = new Hdr(*m.pH);
pT = new Txt(*m.pT);
return *this;
}
};
int main()
{
Msg *pMsg = new Msg;
return 0;
} |
Listing #1: Unsafe Exception Example
Types of Exception Safety
A piece of code can be exception unsafe, neutral, or safe. Exception
unsafe code leaks resources and/or leaves partially constructed
objects around after an exception is thrown. Exception neutral
code passes back all exceptions to the caller. Exception safe code
works correctly when exceptions occur and does not leak resources or
leave invalid object fragments. There is also basic, strong and
no-throw exception safe safety guarantees. The basic exception
safety guarantee ensures three things:
- Destructors don’t throw exceptions
- There are no resource leaks
- The state of variables or class instances are valid and
useable.
The strong exception safety guarantee adds a fourth rule:
- The state of an instance is the same before and after if an
exception is thrown.
The no-throw exception safety guarantee adds the most
stringent fifth rule:
- The piece of code will not throw an exception.
Guidelines
To make this all happen, Herb Sutter [1] has given a series of
guidelines:
- Ensure that no exception escapes from a destructor, overloaded
operator delete() or operator
delete[]().
- Move all code that might cause an exception into another
function or try/catch block; and only when all that code is
executes correctly, change the state of the instance.
- Give each code fragment (module, class, function) a single well-define
responsibility.
- Exception safety is a design consideration. It must be built
in, not added as an afterthought.
- Separate out memory allocation from object construction and
destruction.
- Use the Resource Acquisition Is Initialization idiom to
isolate resource allocation and management.
- Use the Acquisition Before Release idiom to ensure that
resource is not leaked.
- An object may own at most one object (see Griffiths [2])
For basic data types like int and pointer, this is always the
case.
The rewritten example in Listing #2 uses these guidelines and
idioms to make the example exception safe. Given the complex
problems it solves, the implementation is much cleaner than one
would expect.
#include
<algorithm>
using namespace std;
class Hdr { /* … */ }; // assume variable header
size
class Txt { /* … */ }; // assume variable text body size
class Msg { // Composite class
// use auto_ptr to handle allocate/release
auto_ptr<Hdr> pH;
auto_ptr<Txt> pT;
public:
// uses Resource Acquisition is
Initialization
Msg() : pH(new Hdr), pT(new Txt) { }
Msg(const Msg& m)
: pH(new Hdr(*m.pH)), pT(new Txt(*m.pT))
{ }
void swap(Msg& m) // use member
function since
{
// std::swap fails with auto_ptr
auto_ptr<Hdr>
t1(m.pH);
auto_ptr<Txt>
t2(m.pT);
m.pH = pH;
pH = t1;
m.pT = pT;
pT = t2;
}
Msg& operator=(const Msg& m) //
nothrow assignment
{
Msg cpy(m); //
make copy of m
swap(cpy); //
swap copy with *this
return *this; //
return overwritten this
}
};
namespace std { // extend std::swap for Msg objects by
template<> // specializing
for whole Msg objects
inline void swap(Msg& m1, Msg&
m2) { m1.swap(m2); }
}
int main()
{
Msg *pMsg = new Msg;
// . . .
delete pMsg;
return 0;
} |
Listing #2: Safe Exception
example
Let me know is you see anything that interests you.
References
- Exceptional C++
by Herb Sutter, Addison-Wesley, ISBN
0-201-61562-2
Here Be Dragons by Alan Griffiths C/C++ Users Journal, March
2001
The C++ Programming Language: Special Edition by Bjarne
Stroustrup Addison-Wesley, ISBN 0-201-70073-5
By Reg. Charney
In the newspaper world, there is the concept of the “dog days
of summer” when there was no news. In terms of trends, that about
describes what is happening now. Everyone is waiting for the other
show to drop. Are we heading into a recession or a recovery. I am
here to tell you that nothing much has changed from last month.
Things are still slowing down, but at a very gradual rate. Since you
have all heard this before, I am not going to repeat myself, but
give over my usual space to a more comprehensive book review from
Allan Kelly.
By Allan Kelly
Generative
Programming by Krysztof Czarnecki and Ulrich
Eisenecker, Addison-Wesley, ISBN 0-201-30977-7.
My review copy of this book was handed to me with the cautionary
tale that another ACCU regular had declined to review it saying “a
good review would need an entire book itself!”. I’ll try to give
you something of the a flavour of this book so you can decide for
yourself.
The book is split into three parts. In part one, the authors set
out their thesis that there is a difference between engineering for
re-use and engineering with re-use. If we wish to achieve
re-usability, we must look at ways of automatically generating
systems using code generators, libraries, frameworks and other
tools. While no generator will be applicable to all problems we can
identify families of problems within a domain which have common
abstractions. This introduces the concept of domain engineering
and the idea of dividing our effort between component system
engineering and application system engineering. This is
an idea I have practised myself so it is good to see it codified and
explored.
Part two is a chapter by chapter review of technologies that play
to this paradigm. The reviews help further the central thesis and
show how the technology under review can be applied. While
interesting, it does add a lot of material (400 pages out of 800)
which isn’t core and often doesn’t add to their argument.
Part three give examples. Unfortunately these are laboratory
examples, and each one is a well known problem: list, matrix and
bank accounts. The true value of any new technique is not in how
well one can use it to implement a well understood problem but how
well it deals with those which we only come to understand as we
apply the technique. I would rather have seen a case study of a real
project.
In the name of engineering for re-use the authors attack every
possible point of variance within a system hoping to make it more
re-usable. Looking for points of variance is a useful technique, but
when taken to extremes I think it detracts from the maintainability
of a system – the cure is worse than the disease.
In part the authors response is that since the code should be
generated, we don’t need to maintain it. However, this just moves
the problem to the maintenance of the generators or domain specific
language (DSL). Here the lack of real world contact shows:
maintenance issues, problems with DSLs, the high failure rate of
framework projects and several other issues are not discussed at
all..
Domain analysis and engineering is a fresh way of looking at a
class of problems, and would certainly be essential if we wish to
produce a framework with code generators but I’m concerned that it
is also a Catch-22: if we define the domain too broadly then
we will never escape analysis paralysis ; however, define it
too narrowly and you will defeat the objective. My experience
suggests that no matter how wide we draw the boundary it will never
be wide enough to capture all variation points : Outside Context
Problems are always possible.
The case studies show that basically, generative programming
means generic programming with templates and that DSLs are limited
to configuration of these templates.
In conclusion, this book is worth reading because it has many
fresh ideas which will stretch your thinking and reconsider some
ideas. It also brings some new tools to the multi-paradigm approach
which is a good thing. However, much of the material is too academic
for day to day use, both in the approach of the authors and in the
applicability of some ideas.
By Reg. Charney
Last month I talked about all the trends being in lock step. This
month seems to continue that trend. However, the most pressing
problem is: “Will the downward trend grow worse or not?”

Figure #1 shows the normalized job demand for IT
skills and demand for software engineers both in the U.S., in
general, and in Silicon Valley, in particular. Notice that the
decrease of job openings has leveled off over the last six months.

Figure #2 shows the absolute change in the normalized number of
job. That is, it shows that the rate of change of job openings has
stabilized. The radical changes in job openings has cycled down to
the point where the rate of job openings is almost zero.
Because of the lack of change, there is little to report. This is
in stark contrast to all the headlines we have seen in the last few
months proclaiming all sorts of layoffs. Since the trends we have
been plotting have usually preceded major changes by about a month,
these trend lines indicate that the layoffs have had no real or
immediate impact on the IT job market.
That said, we are now running at about 1/3 the job openings that
we did at the beginning of last year.
Recently, the top technologies (highest to lowest) requested in
job postings are:
ASP
Web
TCP/IP
Object-Oriented
Design
COM
Figure #3 shows that the most dramatic changes in technology
demand is in the areas of database and ASIC skills. This falloff in
the skills listed is consistent with the problems that internet
companies and chip manufacturers are having at the moment. However,
there is still a growing demand for ASP and client/server software
skills.

Thanks to DICE at www.dice.com
for a truly valuable service and allowing me to analyze some of
their data.
|