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