Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals

myexcept.cpp

Go to the documentation of this file.
00001 //$$myexcept.cpp                        Exception handler
00002 
00003 // Copyright (C) 1993,4,6: R B Davies
00004 
00005 #include "SdlArs.h"
00006 
00007 //#define WANT_STREAM                    // include.h will get stream fns
00008 
00009 #include <string.h>                    // C string library
00010 
00011 #include "include.h"                   // include standard files
00012 
00013 
00014 #include "myexcept.h"                  // for exception handling
00015 
00016 #ifdef use_namespace
00017 namespace RBD_COMMON {
00018 #endif
00019 
00020 
00021 //#define REG_DEREG                    // for print out uses of new/delete
00022 //#define CLEAN_LIST                   // to print entries being added to
00023                                        // or deleted from cleanup list
00024 
00025 #ifdef SimulateExceptions
00026 
00027 void Throw()
00028 {
00029    for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
00030       jan->CleanUp();
00031    JumpItem* jx = JumpBase::jl->ji;    // previous jumpbase;
00032    if ( !jx ) { Terminate(); }         // jl was initial JumpItem
00033    JumpBase::jl = jx;                  // drop down a level; cannot be in front
00034                                        // of previous line
00035    Tracer::last = JumpBase::jl->trace;
00036    longjmp(JumpBase::jl->env, 1);
00037 }
00038 
00039 #endif                                 // end of simulate exceptions
00040 
00041 
00042 unsigned long Exception::Select;
00043 char* Exception::what_error;
00044 int Exception::SoFar;
00045 int Exception::LastOne;
00046 
00047 Exception::Exception(const char* a_what)
00048 {
00049    Select++; SoFar = 0;
00050    if (!what_error)                   // make space for exception message
00051    {
00052       LastOne = 511;
00053       what_error = new char[512];
00054       if (!what_error)                // fail to make space
00055       {
00056          LastOne = 0;
00057          what_error = "No heap space for exception message\n";
00058       }
00059    }
00060    AddMessage("\n\nAn exception has been thrown\n");
00061    AddMessage(a_what);
00062    if (a_what) Tracer::AddTrace();
00063 }
00064 
00065 void Exception::AddMessage(const char* a_what)
00066 {
00067    if (a_what)
00068    {
00069       int l = strlen(a_what); int r = LastOne - SoFar;
00070       if (l < r) { strcpy(what_error+SoFar, a_what); SoFar += l; }
00071       else if (r > 0)
00072       {
00073          strncpy(what_error+SoFar, a_what, r);
00074          what_error[LastOne] = 0;
00075          SoFar = LastOne;
00076       }
00077    }
00078 }
00079 
00080 void Exception::AddInt(int value)
00081 {
00082    bool negative;
00083    if (value == 0) { AddMessage("0"); return; }
00084    else if (value < 0) { value = -value; negative = true; }
00085    else negative = false;
00086    int n = 0; int v = value;        // how many digits will we need?
00087    while (v > 0) { v /= 10; n++; }
00088    if (negative) n++;
00089    if (LastOne-SoFar < n) { AddMessage("***"); return; }
00090 
00091    SoFar += n; n = SoFar; what_error[n] = 0;
00092    while (value > 0)
00093    {
00094       int nv = value / 10; int rm = value - nv * 10;  value = nv;
00095       what_error[--n] = (char)(rm + '0');
00096    }
00097    if (negative) what_error[--n] = '-';
00098    return;
00099 }
00100 
00101 void Tracer::PrintTrace()
00102 {
00103 /*
00104    cout << "\n";
00105    for (Tracer* et = last; et; et=et->previous)
00106       cout << "  * " << et->entry << "\n";
00107 */
00108 }
00109 
00110 void Tracer::AddTrace()
00111 {
00112    if (last)
00113    {
00114       Exception::AddMessage("Trace: ");
00115       Exception::AddMessage(last->entry);
00116       for (Tracer* et = last->previous; et; et=et->previous)
00117       {
00118          Exception::AddMessage("; ");
00119          Exception::AddMessage(et->entry);
00120       }
00121       Exception::AddMessage(".\n");
00122    }
00123 }
00124 
00125 #ifdef SimulateExceptions
00126 
00127 
00128 Janitor::Janitor()
00129 {
00130    if (do_not_link)
00131    {
00132       do_not_link = false; NextJanitor = 0; OnStack = false;
00133 #ifdef CLEAN_LIST
00134       cout << "Not added to clean-list " << (unsigned long)this << "\n";
00135 #endif
00136    }
00137    else
00138    {
00139       OnStack = true;
00140 #ifdef CLEAN_LIST
00141       cout << "Add to       clean-list " << (unsigned long)this << "\n";
00142 #endif
00143       NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
00144    }
00145 }
00146 
00147 Janitor::~Janitor()
00148 {
00149    // expect the item to be deleted to be first on list
00150    // but must be prepared to search list
00151    if (OnStack)
00152    {
00153 #ifdef CLEAN_LIST
00154       cout << "Delete from  clean-list " << (unsigned long)this << "\n";
00155 #endif
00156       Janitor* lastjan = JumpBase::jl->janitor;
00157       if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
00158       else
00159       {
00160          for (Janitor* jan = lastjan->NextJanitor; jan;
00161             jan = lastjan->NextJanitor)
00162          {
00163             if (jan==this)
00164                { lastjan->NextJanitor = jan->NextJanitor; return; }
00165             lastjan=jan;
00166          }
00167 
00168          Throw(Exception(
00169 "Cannot resolve memory linked list\nSee notes in myexcept.cpp for details\n"
00170          ));
00171 
00172 
00173 // This message occurs when a call to ~Janitor() occurs, apparently
00174 // without a corresponding call to Janitor(). This could happen if my
00175 // way of deciding whether a constructor is being called by new
00176 // fails.
00177 
00178 // It may happen if you are using my simulated exceptions and also have
00179 // your compiler s exceptions turned on.
00180 
00181 // It can also happen if you have a class derived from Janitor
00182 // which does not include a copy constructor [ eg X(const &X) ].
00183 // Possibly also if delete is applied an object on the stack (ie not
00184 // called by new). Otherwise, it is a bug in myexcept or your compiler.
00185 // If you do not #define TEMPS_DESTROYED_QUICKLY you will get this
00186 // error with Microsoft C 7.0. There are probably situations where
00187 // you will get this when you do define TEMPS_DESTROYED_QUICKLY. This
00188 // is a bug in MSC. Beware of "operator" statements for defining
00189 // conversions; particularly for converting from a Base class to a
00190 // Derived class.
00191 
00192 // You may get away with simply deleting this error message and Throw
00193 // statement if you can not find a better way of overcoming the
00194 // problem. In any case please tell me if you get this error message,
00195 // particularly for compilers apart from Microsoft C 7.0.
00196 
00197 
00198       }
00199    }
00200 }
00201 
00202 JumpItem* JumpBase::jl;              // will be set to zero
00203 jmp_buf JumpBase::env;
00204 bool Janitor::do_not_link;           // will be set to false
00205 
00206 
00207 int JanitorInitializer::ref_count;
00208 
00209 JanitorInitializer::JanitorInitializer()
00210 {
00211    if (ref_count++ == 0) new JumpItem;
00212                                     // need JumpItem at head of list
00213 }
00214 
00215 #endif                              // end of SimulateExceptions
00216 
00217 Tracer* Tracer::last;               // will be set to zero
00218 
00219 
00220 void Terminate()
00221 {
00222 //   cout << "\n\nThere has been an exception with no handler - exiting";
00223    const char* what = Exception::what();
00224 //   if (what) cout << what << "\n";
00225    exit(1);
00226 }
00227 
00228 
00229 
00230 #ifdef DO_FREE_CHECK
00231 // Routines for tracing whether new and delete calls are balanced
00232 
00233 FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
00234    { FreeCheck::next = this; }
00235 
00236 FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
00237 
00238 FCLRealArray::FCLRealArray(void* t, char* o, int s)
00239   : Operation(o), size(s) { ClassStore=t; }
00240 
00241 FCLIntArray::FCLIntArray(void* t, char* o, int s)
00242   : Operation(o), size(s) { ClassStore=t; }
00243 
00244 FreeCheckLink* FreeCheck::next;
00245 int FreeCheck::BadDelete;
00246 
00247 void FCLClass::Report()
00248 { cout << "   " << ClassName << "   " << (unsigned long)ClassStore << "\n"; }
00249 
00250 void FCLRealArray::Report()
00251 {
00252    cout << "   " << Operation << "   " << (unsigned long)ClassStore <<
00253       "   " << size << "\n";
00254 }
00255 
00256 void FCLIntArray::Report()
00257 {
00258    cout << "   " << Operation << "   " << (unsigned long)ClassStore <<
00259       "   " << size << "\n";
00260 }
00261 
00262 void FreeCheck::Register(void* t, char* name)
00263 {
00264    FCLClass* f = new FCLClass(t,name);
00265    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
00266 #ifdef REG_DEREG
00267    cout << "Registering   " << name << "   " << (unsigned long)t << "\n";
00268 #endif
00269 }
00270 
00271 void FreeCheck::RegisterR(void* t, char* o, int s)
00272 {
00273    FCLRealArray* f = new FCLRealArray(t,o,s);
00274    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
00275 #ifdef REG_DEREG
00276    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
00277 #endif
00278 }
00279 
00280 void FreeCheck::RegisterI(void* t, char* o, int s)
00281 {
00282    FCLIntArray* f = new FCLIntArray(t,o,s);
00283    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
00284 #ifdef REG_DEREG
00285    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
00286 #endif
00287 }
00288 
00289 void FreeCheck::DeRegister(void* t, char* name)
00290 {
00291    FreeCheckLink* last = 0;
00292 #ifdef REG_DEREG
00293    cout << "Deregistering " << name << "   " << (unsigned long)t << "\n";
00294 #endif
00295    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
00296    {
00297       if (fcl->ClassStore==t)
00298       {
00299          if (last) last->next = fcl->next; else next = fcl->next;
00300          delete fcl; return;
00301       }
00302       last = fcl;
00303    }
00304    cout << "\nRequest to delete non-existent object of class and location:\n";
00305    cout << "   " << name << "   " << (unsigned long)t << "\n";
00306    BadDelete++;
00307    Tracer::PrintTrace();
00308    cout << "\n";
00309 }
00310 
00311 void FreeCheck::DeRegisterR(void* t, char* o, int s)
00312 {
00313    FreeCheckLink* last = 0;
00314 #ifdef REG_DEREG
00315    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
00316 #endif
00317    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
00318    {
00319       if (fcl->ClassStore==t)
00320       {
00321          if (last) last->next = fcl->next; else next = fcl->next;
00322          if (s >= 0 && ((FCLRealArray*)fcl)->size != s)
00323          {
00324             cout << "\nArray sizes do not agree:\n";
00325             cout << "   " << o << "   " << (unsigned long)t
00326                << "   " << ((FCLRealArray*)fcl)->size << "   " << s << "\n";
00327             Tracer::PrintTrace();
00328             cout << "\n";
00329          }
00330          delete fcl; return;
00331       }
00332       last = fcl;
00333    }
00334    cout << "\nRequest to delete non-existent real array:\n";
00335    cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
00336    BadDelete++;
00337    Tracer::PrintTrace();
00338    cout << "\n";
00339 }
00340 
00341 void FreeCheck::DeRegisterI(void* t, char* o, int s)
00342 {
00343    FreeCheckLink* last = 0;
00344 #ifdef REG_DEREG
00345    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
00346 #endif
00347    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
00348    {
00349       if (fcl->ClassStore==t)
00350       {
00351          if (last) last->next = fcl->next; else next = fcl->next;
00352          if (s >= 0 && ((FCLIntArray*)fcl)->size != s)
00353          {
00354             cout << "\nArray sizes do not agree:\n";
00355             cout << "   " << o << "   " << (unsigned long)t
00356                << "   " << ((FCLIntArray*)fcl)->size << "   " << s << "\n";
00357             Tracer::PrintTrace();
00358             cout << "\n";
00359          }
00360          delete fcl; return;
00361       }
00362       last = fcl;
00363    }
00364    cout << "\nRequest to delete non-existent int array:\n";
00365    cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
00366    BadDelete++;
00367    Tracer::PrintTrace();
00368    cout << "\n";
00369 }
00370 
00371 void FreeCheck::Status()
00372 {
00373    if (next)
00374    {
00375       cout << "\nObjects of the following classes remain undeleted:\n";
00376       for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
00377       cout << "\n";
00378    }
00379    else cout << "\nNo objects remain undeleted\n\n";
00380    if (BadDelete)
00381    {
00382       cout << "\nThere were " << BadDelete << 
00383          " requests to delete non-existent items\n\n";
00384    }
00385 }
00386 
00387 #endif                            // end of DO_FREE_CHECK
00388 
00389 // derived exception bodies
00390 
00391 Logic_error::Logic_error(const char* a_what) : Exception()
00392 {
00393    Select = Exception::Select;
00394    AddMessage("Logic error:- "); AddMessage(a_what);
00395    if (a_what) Tracer::AddTrace();
00396 }
00397 
00398 Runtime_error::Runtime_error(const char* a_what)
00399    : Exception()
00400 {
00401    Select = Exception::Select;
00402    AddMessage("Runtime error:- "); AddMessage(a_what);
00403    if (a_what) Tracer::AddTrace();
00404 }
00405 
00406 Domain_error::Domain_error(const char* a_what) : Logic_error()
00407 {
00408    Select = Exception::Select;
00409    AddMessage("domain error\n"); AddMessage(a_what);
00410    if (a_what) Tracer::AddTrace();
00411 }
00412 
00413 Invalid_argument::Invalid_argument(const char* a_what) : Logic_error()
00414 {
00415    Select = Exception::Select;
00416    AddMessage("invalid argument\n"); AddMessage(a_what);
00417    if (a_what) Tracer::AddTrace();
00418 }
00419 
00420 Length_error::Length_error(const char* a_what) : Logic_error()
00421 {
00422    Select = Exception::Select;
00423    AddMessage("length error\n"); AddMessage(a_what);
00424    if (a_what) Tracer::AddTrace();
00425 }
00426 
00427 Out_of_range::Out_of_range(const char* a_what) : Logic_error()
00428 {
00429    Select = Exception::Select;
00430    AddMessage("out of range\n"); AddMessage(a_what);
00431    if (a_what) Tracer::AddTrace();
00432 }
00433 
00434 Bad_cast::Bad_cast(const char* a_what) : Logic_error()
00435 {
00436    Select = Exception::Select;
00437    AddMessage("bad cast\n"); AddMessage(a_what);
00438    if (a_what) Tracer::AddTrace();
00439 }
00440 
00441 Bad_typeid::Bad_typeid(const char* a_what) : Logic_error()
00442 {
00443    Select = Exception::Select;
00444    AddMessage("bad type id.\n"); AddMessage(a_what);
00445    if (a_what) Tracer::AddTrace();
00446 }
00447 
00448 Range_error::Range_error(const char* a_what) : Runtime_error()
00449 {
00450    Select = Exception::Select;
00451    AddMessage("range error\n"); AddMessage(a_what);
00452    if (a_what) Tracer::AddTrace();
00453 }
00454 
00455 Overflow_error::Overflow_error(const char* a_what) : Runtime_error()
00456 {
00457    Select = Exception::Select;
00458    AddMessage("overflow error\n"); AddMessage(a_what);
00459    if (a_what) Tracer::AddTrace();
00460 }
00461 
00462 Bad_alloc::Bad_alloc(const char* a_what) : Exception()
00463 {
00464    Select = Exception::Select;
00465    AddMessage("bad allocation\n"); AddMessage(a_what);
00466    if (a_what) Tracer::AddTrace();
00467 }
00468 
00469 
00470 
00471 
00472 unsigned long Logic_error::Select;
00473 unsigned long Runtime_error::Select;
00474 unsigned long Domain_error::Select;
00475 unsigned long Invalid_argument::Select;
00476 unsigned long Length_error::Select;
00477 unsigned long Out_of_range::Select;
00478 unsigned long Bad_cast::Select;
00479 unsigned long Bad_typeid::Select;
00480 unsigned long Range_error::Select;
00481 unsigned long Overflow_error::Select;
00482 unsigned long Bad_alloc::Select;
00483 
00484 #ifdef use_namespace
00485 }
00486 #endif
00487 
00488 

Generated on Fri Dec 5 04:06:00 2003 for Borqueror by doxygen 1.3.3