Quick quiz: What is the behavior of the following code:
int main(int argc, char* argv)
*((char*) 0) = 1;
Surprisingly, it depends! As I would expect, on many operating system / compiler combinations (such as
gcc version 3.4.4 20050721 (Red Hat 3.4.4-2) as tested by Keith Garner), the dereference of the null pointer leads to a segmentation fault. However, both Microsoft Visual Studio 6.0 and Visual Studio .NET 2003 print the message
Caught exception. and exit gracefully. Strange!
This behavior appears to be an unintended consequence of the way C++ exceptions were implemented by Microsoft. Seemingly, Visual C++ implements the C++ exception handling mechanism using Structured Exception Handling (SEH), and the null pointer dereference leads to a Structured Exception, most likely an
EXCEPTION_ACCESS_VIOLATION. (For a list of possible SEH codes, see the documentation for the
GetExceptionCode() function.) The
catch (...) statement ends up catching the Structured Exception, and the code proceeds accordingly.
This means that in Visual C++ 6.0 and Visual C++ .NET 2003,
catch (...) does not catch only exceptions thrown using the C++
throw keyword; rather, it may also catch any number of Structured Exceptions, including division by 0, stack overflow, data misalignment, etc. Fortunately, it seems that this behavior may be disabled with the
/EHs compiler option in Visual C++ .NET 2005.
However, until the day comes when all Windows code is compiled with Visual C++ .NET 2005 and the
/EHs option, I suggest avoiding the
catch (...) construct altogether. Personally, I’ve chosen to inherit my custom-defined exceptions from STL’s
std::exception and use
catch (const std::exception& ex) instead.
This is part 14 of my Implementing
IXmlWriter post series.
Today I will add support for writing the generated XML to a C++ stream to last time’s
Finally the reason why I’ve insisted on calling this series
IXmlWriter (instead of
StringXmlWriter) should become clear: I’ve been planning on supporting writing the generated XML to more than just a string. Specifically, today I will add the ability to write the XML to a C++
ostream object, a base class in the C++ iostream library which defines a writable stream.
To this end, I decided to write a pure-virtual interface called
IXmlWriter which contains all the relevant methods for generating XML (e.g.
WriteComment(), etc.), and two concrete classes which implement this interface:
StringXmlWriter (which writes to a string as before) and
OstreamXmlWriter (which writes to a user-provided
ostream instance). I moved the XML-generating logic from
OstreamXmlWriter and implemented
StringXmlWriter in terms of
OstreamXmlWriter and a
The area where I probably spent the most time was deciding how to pass the
ostream instance to
OstreamXmlWriter and how
OstreamXmlWriter would store it, if necessary. I came up with the following options:
OstreamXmlWriter is passed a copy (or const reference) of the
ostream instance in its constructor and stores a copy of the
ostream instance as a member variable. Advantages: The typical idiom for most variables passed in the constructor. Disadvantages: For correctness, this requires a semantically correct copy constructor which is very difficult, and often impossible, to write for streams.
OstreamXmlWriter is passed a reference (pointer) to the
ostream instance in its constructor and stores a reference (pointer) to the
ostream instance as a member variable. Advantages: Relatively simple. Disadvantages:
OstreamXmlWriter becomes implicitly tied to the lifetime of the passed object, which means that a user must be sure that
OstreamXmlWriter is destroyed before the
ostream instance is. Code such as
stringstream* ss = new stringstream(); XmlWriter w(ss); delete ss; w.WriteStartElement("blah"); may result in hard-to-find bugs.
OstreamXmlWriter is passed a smart pointer object (e.g.
boost::shared_ptr) which points to the
ostream instance in its constructor and stores a copy of the smart pointer object as a member variable. Advantages: Lifetime issues are handled correctly. Disadvantages: The
ostream instance must be constructed on the heap and never the stack. We expose a dependency on a smart pointer implementation that users probably shouldn’t care about. (Alternative: Take a heap-constructed
ostream* in the constructor, store as a smart pointer member variable. However, what if a stack-constructed
ostream is passed?)</li
OstreamXmlWriter takes a reference to the
ostream instance as an extra parameter for every XML writing function. Advantages: Parallels
operator<<, no lifetime issues. Disadvantages: Breaks
Based on these observations, I decided to go with (2). Here’s the new test case:
OstreamXmlWriter xmlWriter(ss, StringXmlWriter::Formatting_Indented);
// ss.str() should equal (whitespace is important):
// <child att="value"/>
Because the source code is starting to get unwieldy (chorus: Too late!), I have linked to the source code files rather than insert the source code in-line with the post. Here’s the latest source code:
Unfortunately, the source code for this post has been lost.