home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / sources / misc / 4254 / except.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-11  |  7.4 KB  |  287 lines

  1. //$$except.cxx                        Exception handler
  2.  
  3.  
  4.  
  5. #define WANT_STREAM                  // include.h will get stream fns
  6.  
  7.  
  8. #include "include.h"                 // include standard files
  9. #include "boolean.h"
  10.  
  11.  
  12. #include "except.h"                  // for exception handling
  13.  
  14. //#define REG_DEREG                    // for print out uses of new/delete
  15. //#define CLEAN_LIST                   // to print entries being added to
  16.                                        // or deleted from cleanup list
  17.  
  18.  
  19. void Throw()
  20. {
  21.    for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
  22.       jan->CleanUp();
  23.    JumpBase::jl = JumpBase::jl->ji;
  24.    if ( ! JumpBase::jl ) Terminate();
  25.    Exception::last = JumpBase::jl->trace;
  26.    longjmp(JumpBase::jl->env, 1);
  27. }
  28.  
  29. void Throw(const Exception& exc) { JumpBase::type = exc.type(); Throw(); }
  30.  
  31.  
  32. void Exception::PrintTrace(Boolean)
  33. {
  34.    cout << "\n";
  35.    {
  36.       for (Tracer* et = last; et; et=et->previous)
  37.      cout << "  * " << et->entry << "\n";
  38.    }
  39. }
  40.  
  41. Exception::Exception(int action)
  42. {
  43.    if (action)
  44.    {
  45.       cout << "\nAn exception has occurred: call trace follows.";
  46.       PrintTrace();
  47.       if (action < 0) exit(1);
  48.    }
  49. }
  50.  
  51. Janitor::Janitor()
  52. {
  53.    if (do_not_link)
  54.    {
  55.       do_not_link = FALSE; NextJanitor = 0; OnStack = FALSE;
  56. #ifdef CLEAN_LIST
  57.       cout << "Not added to clean-list " << (unsigned long)this << "\n";
  58. #endif
  59.    }
  60.    else
  61.    {
  62.       OnStack = TRUE;
  63. #ifdef CLEAN_LIST
  64.       cout << "Add to       clean-list " << (unsigned long)this << "\n";
  65. #endif
  66.       NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
  67.    }
  68. }
  69.  
  70. Janitor::~Janitor()
  71. {
  72.    // expect the item to be deleted to be first on list
  73.    // but must be prepared to search list
  74.    if (OnStack)
  75.    {
  76. #ifdef CLEAN_LIST
  77.       cout << "Delete from  clean-list " << (unsigned long)this << "\n";
  78. #endif
  79.       Janitor* lastjan = JumpBase::jl->janitor;
  80.       if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
  81.       else
  82.       {
  83.      for (Janitor* jan = lastjan->NextJanitor; jan;
  84.         jan = lastjan->NextJanitor)
  85.      {
  86.         if (jan==this)
  87.            { lastjan->NextJanitor = jan->NextJanitor; return; }
  88.         lastjan=jan;
  89.      }
  90.  
  91.          cout << "\nCannot resolve memory linked list\n";
  92.          cout << "See notes in except.cxx for details\n";
  93.      Throw(Exception(-1));
  94. /*
  95. This message occurs when a call to ~Janitor() occurs, apparently without a
  96. corresponding call to Janitor(). This could happen if my way of deciding
  97. whether a constructor is being called by new fails. Possibly also if
  98. delete is applied an object on the stack (ie not called by new). Otherwise,
  99. it is a bug in Newmat or your compiler. If you don't #define
  100. TEMPS_DESTROYED_QUICKLY you will get this error with Microsoft C 7.0. There
  101. are probably situations where you will get this when you do define
  102. TEMPS_DESTROYED_QUICKLY. This is a bug in MSC. Beware of "operator" statements
  103. for defining conversions; particularly for converting from a Base class to
  104. a Derived class. 
  105.  
  106. You may get away with simply deleting this error message and Throw statement
  107. if you can't find a better way of overcoming the problem. In any case please
  108. tell me if you get this error message, particularly for compilers apart from
  109. Microsoft C.
  110. */
  111.       }
  112.    }
  113. }
  114.  
  115. JumpItem* JumpBase::jl = 0;
  116. long JumpBase::type;
  117. Tracer* Exception::last = 0;
  118.  
  119. Boolean Janitor::do_not_link = FALSE;
  120.  
  121. static JumpItem JI;                  // need JumpItem at head of list
  122.  
  123.  
  124.  
  125. void Terminate()
  126. {
  127.    cout << "\nThere has been an exception with no handler - exiting\n";
  128.    exit(1);
  129. }
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136. #ifdef DO_FREE_CHECK
  137. // Routines for tracing whether new and delete calls are balanced
  138.  
  139. FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
  140.    { FreeCheck::next = this; }
  141.  
  142. FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
  143.    
  144. FCLRealArray::FCLRealArray(void* t, char* o, int s)
  145.   : Operation(o), size(s) { ClassStore=t; }
  146.  
  147. FCLIntArray::FCLIntArray(void* t, char* o, int s)
  148.   : Operation(o), size(s) { ClassStore=t; }
  149.  
  150. FreeCheckLink* FreeCheck::next = 0;
  151.  
  152. void FCLClass::Report()
  153. { cout << "   " << ClassName << "   " << (unsigned long)ClassStore << "\n"; }
  154.  
  155. void FCLRealArray::Report()
  156. {
  157.    cout << "   " << Operation << "   " << (unsigned long)ClassStore << 
  158.       "   " << size << "\n";
  159. }
  160.  
  161. void FCLIntArray::Report()
  162. {
  163.    cout << "   " << Operation << "   " << (unsigned long)ClassStore << 
  164.       "   " << size << "\n";
  165. }
  166.  
  167. void FreeCheck::Register(void* t, char* name)
  168. {
  169.    FCLClass* f = new FCLClass(t,name);
  170.    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
  171. #ifdef REG_DEREG
  172.    cout << "Registering   " << name << "   " << (unsigned long)t << "\n";
  173. #endif
  174. }
  175.  
  176. void FreeCheck::RegisterR(void* t, char* o, int s)
  177. {
  178.    FCLRealArray* f = new FCLRealArray(t,o,s);
  179.    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
  180. #ifdef REG_DEREG
  181.    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
  182. #endif
  183. }
  184.  
  185. void FreeCheck::RegisterI(void* t, char* o, int s)
  186. {
  187.    FCLIntArray* f = new FCLIntArray(t,o,s);
  188.    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
  189. #ifdef REG_DEREG
  190.    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
  191. #endif
  192. }
  193.  
  194. void FreeCheck::DeRegister(void* t, char* name)
  195. {
  196.    FreeCheckLink* last = 0;
  197. #ifdef REG_DEREG
  198.    cout << "Deregistering " << name << "   " << (unsigned long)t << "\n";
  199. #endif
  200.    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
  201.    {
  202.       if (fcl->ClassStore==t)
  203.       {
  204.      if (last) last->next = fcl->next; else next = fcl->next;
  205.      delete fcl; return;
  206.       }
  207.       last = fcl;
  208.    }
  209.    cout << "\nRequest to delete non-existent object of class and location:\n";
  210.    cout << "   " << name << "   " << (unsigned long)t << "\n";
  211.    Exception::PrintTrace(TRUE);
  212.    cout << "\n";
  213. }
  214.  
  215. void FreeCheck::DeRegisterR(void* t, char* o, int s)
  216. {
  217.    FreeCheckLink* last = 0;
  218. #ifdef REG_DEREG
  219.    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
  220. #endif
  221.    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
  222.    {
  223.       if (fcl->ClassStore==t)
  224.       {
  225.      if (last) last->next = fcl->next; else next = fcl->next;
  226.      if (((FCLRealArray*)fcl)->size != s)
  227.      {
  228.         cout << "\nArray sizes don't agree:\n";
  229.         cout << "   " << o << "   " << (unsigned long)t
  230.            << "   " << s << "\n";
  231.         Exception::PrintTrace(TRUE);
  232.         cout << "\n";
  233.      }
  234.      delete fcl; return;
  235.       }
  236.       last = fcl;
  237.    }
  238.    cout << "\nRequest to delete non-existent real array:\n";
  239.    cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
  240.    Exception::PrintTrace(TRUE);
  241.    cout << "\n";
  242. }
  243.  
  244. void FreeCheck::DeRegisterI(void* t, char* o, int s)
  245. {
  246.    FreeCheckLink* last = 0;
  247. #ifdef REG_DEREG
  248.    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
  249. #endif
  250.    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
  251.    {
  252.       if (fcl->ClassStore==t)
  253.       {
  254.      if (last) last->next = fcl->next; else next = fcl->next;
  255.      if (((FCLIntArray*)fcl)->size != s)
  256.      {
  257.         cout << "\nArray sizes don't agree:\n";
  258.         cout << "   " << o << "   " << (unsigned long)t
  259.            << "   " << s << "\n";
  260.         Exception::PrintTrace(TRUE);
  261.         cout << "\n";
  262.      }
  263.      delete fcl; return;
  264.       }
  265.       last = fcl;
  266.    }
  267.    cout << "\nRequest to delete non-existent int array:\n";
  268.    cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
  269.    Exception::PrintTrace(TRUE);
  270.    cout << "\n";
  271. }
  272.  
  273. void FreeCheck::Status()
  274. {
  275.    if (next)
  276.    {
  277.       cout << "\nObjects of the following classes remain undeleted:\n";
  278.       for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
  279.       cout << "\n";
  280.    }
  281.    else cout << "\nNo objects remain undeleted\n";
  282. }
  283.  
  284. #endif
  285.  
  286.  
  287.