Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1693628
  • 博文数量: 177
  • 博客积分: 9416
  • 博客等级: 中将
  • 技术积分: 2513
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-06 16:08
文章分类

全部博文(177)

文章存档

2013年(4)

2012年(13)

2011年(9)

2010年(71)

2009年(12)

2008年(11)

2007年(32)

2006年(25)

分类: C/C++

2011-05-31 12:05:48

First, let's see what does exception handling do in C++.
  • Compares the type of exception object to that of catch blocks to find appropriate catch block.
  • Handles the exception.
  • Stack unwinding.
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:
  • Current ExceptionHandlerList object will be retrieved to get the right TryBlock
  • Optional: if TryBlock object found, search the tryBlocks in current handler with the Location loc to get the CatchBlock list
  • Optional: if TryBlock object found, search the CatchBlock list with type of actual exception to get the actual handler
  • Optional: if CatchBlock found, execute the actual exception handler
  • Call Dtor to destroy all objects ready for unwinding
  • Optional: If no actual exception handler is executed, find previous ExceptionHandlerList object through the prev pointer (until none previous is found), passing the object of Exception to the handler, then repeat the handling procedure.
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:
  • http://blogold.chinaunix.net/u/8818/showart_2177768.html
阅读(1293) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~