SEH转换为C++ Exception

来源:互联网 发布:根域名服务器地址 编辑:程序博客网 时间:2024/06/09 23:55

以下两段摘自MSDN。

The only way to make a rock solid DLL wrapper is to load the buggy DLL in another process, so that if it crashes it doesn't take your primary process down with it.

Catching all C++ exceptions seems reasonable, but catching all structured exceptions is another story. SEH might seem to get you most of the way there, because it allows you to catch access violations, divide-by-zero exceptions, etc.

But what if the buggy DLL happens to touch an uncommitted page from another thread's stack? The memory access will page fault, the exception handler will be invoked, and now that page is no longer a guard page. When that thread needs to grow the stack, it will get an access violation, and the process will crash. (These posts describe this case in more detail.)

Another likely problem: the buggy DLL crashes while holding a synchronization object, but you use SEH to catch the exception. If your process attempts to acquire the same synchronization object, then it deadlocks instead of crashing.

class ExceptionHandler {public:ExceptionHandler() {    m_previousFilter = SetUnhandledExceptionFilter(UnhandledExceptionFilter);}~ExceptionHandler() {SetUnhandledExceptionFilter( m_previousFilter );}private:    static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;static LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo ){}}static ExceptionHandler ExceptionInstance;  // make a global instance of this handlerLPTOP_LEVEL_EXCEPTION_FILTER ExceptionHandler::m_previousFilter;


The first class is designed to properly install a translator at a given point in the stack and ensure that it is reset to the previous value when that stack frame is popped off.

extern void SehTranslatorFunction(unsigned int, struct _EXCEPTION_POINTERS*);class SehGuard{public:    SehGuard()    {        m_prev = _set_se_translator(SehTranslatorFunction);    }    ~SehGuard()    {        _set_se_translator(m_prev);    }private:    _se_translator_function m_prev;};

The second part is to actually throw an exception inside of SehTranslatorFunction.  Also to add an assert so that when an SEH exception is produced. I can break at the point of failure (as opposed to in the catch block where the stack will be unwound).
The above code is from MSDN. The following is the some code example in my project.

Bool Server::InitInstance(){...._set_se_translator(Exception::SE_Translator_Function);....}class  Exception  {public:Exception();Exception(unsigned int code, PEXCEPTION_POINTERS info);virtual ~Exception() { }/////////////////////////////////////////////////////////////////////////////////SE_Translator_Function(): converts C style win api structured exceptions to //  c++ style typed exceptions///////////////////////////////////////////////////////////////////////////////static void SE_Translator_Function(unsigned int code, PEXCEPTION_POINTERS info);bool Process();....};void Exception::SE_Translator_Function(unsigned int code, PEXCEPTION_POINTERS info){// make sure that the msjexhnd.cpp exception handler writes the exception and stack trace into the sys logUnhandledExceptionFilter(info);// now handle it internallyException e(code, info);throw (e);}


Now whenever I hit a point where I want to guard against SEH exceptions, I just put and instance of SehGuard on the stack and catch SehException instances.  No traditional SEH needed.

 

OMG, this topic exception is thrown in Valentine's Day.

原创粉丝点击