$search
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