[原]General Idea of Exception Handling in C++

1405阅读 0评论2011-05-31 fera
分类:C/C++

First, let's see what does exception handling do in C++.
To achieve this:
  1. Objects should be trackable for unwinding - a table storing objects (objects table)
  2. Location of throw should be identifiable (location)
  3. Catch blocks should be attached to corresponding try block (tryblock and catchblocks)
  4. Because of call stack, objects for unwinding and exception handling objects should be linked for unwinding (exception handlers list)
  5. Exception handler should associate tryblock and objects table (exption handler)
So the data structures should be:
  1. // If the exception is not handled, this list will be traversed to unwind all objects.
  2. struct ExceptionHandlerList {
  3.     ExceptionList* prev;
  4.     ExceptionHandler* handler;
  5. };

  6. struct ExceptionHandler {
  7.     TryBlock* tryBlocks;
  8.     UnwindTable* unwind;
  9. };

  10. struct TryBlock {
  11.     Location* region;
  12.     CatchBlock* catchBlocks;
  13. };

  14. struck CatchBlock {
  15.     type_info* typeInfo;
  16.     Instruction* handler;
  17. };

  18. struct UnwindTable {
  19.     void* pObj;
  20.     void (*pDtor)(void* this);
  21.     int next;
  22. };

  23. struct Exception {
  24.     void* pObj; // Actual exception object
  25.     void (*pDtor)(void*); // Dtor of actual exception object
  26.     type_info* typeInfo; // Type info of actual exception
  27.     Location* loc;
  28. }

OK. Now let's check how these work together.
  1. The throw statement will generate an object of Exception using the thrown exception
  2. System call exception handling procedure, taking the object of Exception as argument, in which:
The pseudo code looks like this:
  1. void HandleException(ExceptionHandlerList* cur, Exception* e)
  2. {
  3.     bool handled = false;
  4.     while (!handled)
  5.     {
  6.         TryBlock* tryBlk = FindTryBlock(cur->handler, e);
  7.         if (tryBlk != NULL)
  8.         {
  9.             CatchBlock* catchBlk = FindCatchBlock(tryBlk, e);
  10.             if (catchBlk != NULL)
  11.             {
  12.                 CallHandler(handler, e); // Destroy Exception object e
  13.                 DestroyObjectsInTryBlock(cur->unwind, tryBlk);
  14.                 handled = true;
  15.             }
  16.         }
  17.         if (!handled)
  18.         {
  19.             DestroyObjects(cur->unwind);
  20.             cur = cur->prev;
  21.         }
  22.     }
  23. }
Note: Objects of UnwindTable, TryBlock, CatchBlock, ExceptionHandler are populated during compile time, while objects of Exception and list of ExceptionHandlerList are generated at runtime.

Quite simple, isn't it?

For more info, follow the link in "References".

Reference:
上一篇:[转]编程界10大名言
下一篇:[原]A simple example about call stack of C