Homepage Demos Overview Downloads Tutorials Reference
Credits

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 
00006 #ifndef WANT_STREAM
00007 #define WANT_STREAM                    // include.h will get stream fns
00008 #endif
00009 #ifndef WANT_STRING
00010 #define WANT_STRING
00011 #endif
00012 
00013 #include "include.h"                   // include standard files
00014 
00015 
00016 #include "myexcept.h"                  // for exception handling
00017 
00018 #ifdef use_namespace
00019 namespace RBD_COMMON {
00020 #endif
00021 
00022 
00023 //#define REG_DEREG                    // for print out uses of new/delete
00024 //#define CLEAN_LIST                   // to print entries being added to
00025                                        // or deleted from cleanup list
00026 
00027 #ifdef SimulateExceptions
00028 
00029 void Throw()
00030 {
00031    for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
00032       jan->CleanUp();
00033    JumpItem* jx = JumpBase::jl->ji;    // previous jumpbase;
00034    if ( !jx ) { Terminate(); }         // jl was initial JumpItem
00035    JumpBase::jl = jx;                  // drop down a level; cannot be in front
00036                                        // of previous line
00037    Tracer::last = JumpBase::jl->trace;
00038    longjmp(JumpBase::jl->env, 1);
00039 }
00040 
00041 #endif                                 // end of simulate exceptions
00042 
00043 
00044 unsigned long BaseException::Select;
00045 char* BaseException::what_error;
00046 int BaseException::SoFar;
00047 int BaseException::LastOne;
00048 
00049 BaseException::BaseException(const char* a_what)
00050 {
00051    Select++; SoFar = 0;
00052    if (!what_error)                   // make space for exception message
00053    {
00054       LastOne = 511;
00055       what_error = new char[512];
00056       if (!what_error)                // fail to make space
00057       {
00058          LastOne = 0;
00059          what_error = (char *)"No heap space for exception message\n";
00060       }
00061    }
00062    AddMessage("\n\nAn exception has been thrown\n");
00063    AddMessage(a_what);
00064    if (a_what) Tracer::AddTrace();
00065 }
00066 
00067 void BaseException::AddMessage(const char* a_what)
00068 {
00069    if (a_what)
00070    {
00071       int l = strlen(a_what); int r = LastOne - SoFar;
00072       if (l < r) { strcpy(what_error+SoFar, a_what); SoFar += l; }
00073       else if (r > 0)
00074       {
00075          strncpy(what_error+SoFar, a_what, r);
00076          what_error[LastOne] = 0;
00077          SoFar = LastOne;
00078       }
00079    }
00080 }
00081 
00082 void BaseException::AddInt(int value)
00083 {
00084    bool negative;
00085    if (value == 0) { AddMessage("0"); return; }
00086    else if (value < 0) { value = -value; negative = true; }
00087    else negative = false;
00088    int n = 0; int v = value;        // how many digits will we need?
00089    while (v > 0) { v /= 10; n++; }
00090    if (negative) n++;
00091    if (LastOne-SoFar < n) { AddMessage("***"); return; }
00092 
00093    SoFar += n; n = SoFar; what_error[n] = 0;
00094    while (value > 0)
00095    {
00096       int nv = value / 10; int rm = value - nv * 10;  value = nv;
00097       what_error[--n] = (char)(rm + '0');
00098    }
00099    if (negative) what_error[--n] = '-';
00100    return;
00101 }
00102 
00103 void Tracer::PrintTrace()
00104 {
00105    cout << "\n";
00106    for (Tracer* et = last; et; et=et->previous)
00107       cout << "  * " << et->entry << "\n";
00108 }
00109 
00110 void Tracer::AddTrace()
00111 {
00112    if (last)
00113    {
00114       BaseException::AddMessage("Trace: ");
00115       BaseException::AddMessage(last->entry);
00116       for (Tracer* et = last->previous; et; et=et->previous)
00117       {
00118          BaseException::AddMessage("; ");
00119          BaseException::AddMessage(et->entry);
00120       }
00121       BaseException::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(BaseException(
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 = BaseException::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) : BaseException()
00392 {
00393    Select = BaseException::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    : BaseException()
00400 {
00401    Select = BaseException::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 = BaseException::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 = BaseException::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 = BaseException::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 = BaseException::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 = BaseException::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 = BaseException::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 = BaseException::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 = BaseException::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) : BaseException()
00463 {
00464    Select = BaseException::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 

newmat11b
Generated Tue Aug 16 16:32:00 2005 by Doxygen 1.4.4