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


kni
Author(s): Neuronics AG (see AUTHORS.txt); ROS wrapper by Martin Günther
autogenerated on Mon Oct 6 2014 10:45:33