    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Non-Standard Code</title>
        <link>https://members.accu.org/index.php/articles/1210</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + CVu Journal Vol 15, #2 - Apr 2003</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c109/">152</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-109/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+109/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Non-Standard Code</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 April 2003 13:15:56 +01:00 or Thu, 03 April 2003 13:15:56 +01:00</p>
<p><strong>Summary:</strong>&nbsp;<p>I recently faced a problem which I felt I could only solve using non-standard code, and thought that some of the issues this brought up might be of interest to the readers of CVu.</p></p>
<p><strong>Body:</strong>&nbsp;<div class="section" lang="en">
<div class="titlepage">
<h2><a name="d0e20" id="d0e20"></a></h2>
</div>
<p>I recently faced a problem which I felt I could only solve using
non-standard code, and thought that some of the issues this brought
up might be of interest to the readers of CVu.</p>
<p>Although the example is using the Microsoft compiler, the
principles will hopefully be of general interest.</p>
<p>Firstly, what was my issue?</p>
<p>I'm writing C++ code which uses exceptions, and using some
libraries which can also throw exceptions. Unfortunately it seems
to be hard to provide useful information when exceptions occur,
unless you know the types of exceptions which might be thrown; and
as in this case there were several, unrelated, exception
hierarchies involved as well as character literals this was not
easy to discover.</p>
<p>A common idiom in standard C++ for such cases is to have a
'generic' exception handler function which is called from a catch
statement. This simply re-throws the exception within another
try/catch block where a catch handler is written for each known
type. An extremely simple example of this idiom follows:</p>
<pre class="programlisting">
// Called from within a catch handler to log
// a string from the current exception
void logException() {
  std::string error;
  try {
    // re-throw the exception to have another
    // look at it
    throw; 
  }

  catch(std::exception &amp; ex) {
    error = ex.what();
  }
  catch(CException * pEx) {
    static char szMsg[255];
    pEx-&gt;GetErrorMessage(szMsg,
                         sizeof(szMsg));
    pEx-&gt;Delete();
    error = szMsg;
  }
  // etc etc
  catch(const char *pStr) {
    error = pStr;
  }
  catch(...) {
    // Search me...
    throw;
  }
  std::cerr &lt;&lt; &quot;Uncaught exception: &quot;
            &lt;&lt; error &lt;&lt; std::endl;
}
// Example of use
int main(int argc, char **argv) {
  try {
    return realmain(argc, argv);
  }
  catch(...) {
    logException();
    return EXIT_FAILURE; 
  }
}
</pre>
<p>There were two problems with this approach. The first was that
the idiom does not work in my current environment (Microsoft VC
6.0) because the destructor is called twice for re-thrown
exceptions. This bug appears to have finally gone in VC.NET, but I
need to continue supporting VC 6. The best work around for this bug
is to ensure all destructors for exception objects can be called
twice, but since I didn't write all the exception objects this was
not an option.</p>
<p>The second problem with this approach is that it only works
where you know the complete list of exceptions which can be thrown.
Given the lack of documentation which seems endemic in our industry
it is all too easy to miss one.</p>
<p>What happens then depends on your runtime. The C++ standard
simply says: &quot;If no matching handler is found in a program, the
function <tt class="function">terminate()</tt> is called; whether
or not the stack is unwound before this call to <tt class=
"function">terminate()</tt> is implementation defined&quot;.</p>
<p>My environment produces the message &quot;<tt class=
"literal">Abnormal program termination</tt>&quot; which provides little
help in finding the root cause of the problem.</p>
<p>I decided that the lack of useful information meant I was
spending too much time debugging problems and so I was prepared to
consider using some non-standard code to help me.</p>
<p>It is obvious from how the exception mechanism works that the
runtime must know the type of the thrown object so it can match it
to the appropriate catch handler. I decided that if I could get the
runtime type of the exception many of my problems would be
over.</p>
<p>Unfortunately this is not (yet) possible in standard C++. there
have been a few discussions I have read over the years but, as far
as I know, there still isn't a concrete proposal to provide this
feature.</p>
<p>Of course at this point any Java or C# programmers reading this
article are proably feeling pretty smug, since these languages (for
a variety of sound reasons), provide significantly more information
about exceptions than C++ does.</p>
<p>After some &quot;poking around&quot; in the compiler output and referring
to some articles in MSJ by Matt Peitrek I discovered that I could
write some Microsoft specific code to catch the underlying Win32
exception used to implement Microsoft's exception handling, and
decode it to get hold of the type_info for the thrown
exception.</p>
<p>So my new, highly non-portable code, looks like this:</p>
<pre class="programlisting">
#include &lt;windows.h&gt;
#include &lt;typeinfo&gt;
#include &lt;iostream&gt;

// Microsoft specific code
DWORD logException(_EXCEPTION_POINTERS*
                               pException) {
  // exception code for MSVC C++ exception
  static const int
              MsvcExceptionCode(0xe06d7363);
  // see EXSUP.INC for only public definition
  static const int MagicNumber1(0x19930520);

  PEXCEPTION_RECORD ExceptionRecord =
                pException-&gt;ExceptionRecord;
  if( (ExceptionRecord-&gt;ExceptionCode
                    == MsvcExceptionCode) &amp;&amp;
      (ExceptionRecord-&gt;NumberParameters
                                    == 3) &amp;&amp;
      (ExceptionRecord-&gt;ExceptionInformation[0]
                        == MagicNumber1) ) {
    struct link {
      link *chain;
    };

    // Hackery to get the type_info buried
    // in the data
    link *p = (link*)ExceptionRecord-&gt;
                    ExceptionInformation[2];
    p = p[3].chain;
    p = p[1].chain;
    const std::type_info *t =
       (const std::type_info *)(p[1].chain);

    std::cerr &lt;&lt; &quot;Uncaught exception: &quot;
              &lt;&lt; t-&gt;name() &lt;&lt; std::endl;

    return EXCEPTION_EXECUTE_HANDLER;
  }
  return EXCEPTION_CONTINUE_SEARCH;
}
</pre>
<p>and the corresponding sample usage is:</p>
<pre class="programlisting">
#include &lt;excpt.h&gt;

int main(int argc, char **argv) {
  __try {
    return realmain(argc, argv);
  }
  __except(logException(exception_info())) {}
  return 0;
}
</pre>
<p>However, I have gone from the original code which used standard
C++ features to some code which uses several Microsoft specific
calls and, even worse, a number of undocumented 'magic numbers' and
pointer hacks.</p>
<p>This raises a few questions, and motivated me to write this
article.</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>Is it worth it?</p>
</li>
<li>
<p>How do I encapsulate the trickery?</p>
</li>
<li>
<p>What can I do about maintainability?</p>
</li>
</ol>
</div>
<p>Many people may feel the first question is all that needs
asking, and answering with a resounding NO. However, in this case I
felt that the gain for me of getting out the name of the object
being thrown was greater than the ugliness of the solution. This is
a judgement call, and each problem like this presents different
trade-offs.</p>
<p>There is also a separation between code used for development and
code shipped in production systems. I would be much less happy to
ship a product which relied on this trick for normal operation, but
if something goes wrong handling an uncaught exception I'm not
really much worse off.</p>
<p>Encapsulating the 'trickery' is important for two reasons.</p>
<p>Firstly, I want to be able to write some test harnesses for the
trick code which can be run whenever an upgrade is installed, or
other compiler settings are used, etc.</p>
<p>Secondly, if I find the code fails in some as yet undiscovered
way I want to have a single place to fix.</p>
<p>Thirdly, I want to hide the code so I can 'forget' this
dangerous knowledge.</p>
<p>Hence I want to write this function inside a separate C++ source
file. I would also add checks for the preprocessor symbol for the
compiler to check it matches one of the versions I have tested the
code for. This ensures I explicitly check the code when I move to a
different compiler level, and also prevents me accidently trying to
use this code with a non-Microsoft (in this case) compiler.</p>
<p>The big problem with non-portable code is maintainability. This
is a problem for many reasons.</p>
<p>First of all I have used undocumented features of the compiler
and so my chances of support if anything goes wrong is almost zero.
Since I am using such features I am relying on my guesses about the
structures being right. It is quite likely my guesses are
incomplete, causing the code to break under some conditions.</p>
<p>Then I have a vulnerability to the future - I am at the mercy of
the compiler writers who may well change this sort of internal
detail with a subsequent release of the compiler (or even with a
patch release). Will it be possible for me to change my trick to
cater for the future structures? Will I still be around to do this
work by then, and if not is there anyone else who could?</p>
<p>The best I can do to reduce this vulnerability is to ensure the
function is documented to use non-portable code and provide some
documentation about the 'detective work' which went in to finding
this solution. A good set of test cases exercising the function in
as wide a variety of cases as possible and compiled with as many
versions of the compiler I can find helps greatly with ensuring the
robustness of the solution and also provides a ready made test bed
for future compiler releases.</p>
<p>Having made the function a separate compilation unit, as
described above, also makes it easier to write stand-alone test
cases. I hope this quick run through the issues I thought about
when writing this non-standard piece of code may help you when you
find yourself facing a problem which you can't seem to fix using
the standard set of features.</p>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
