SEH转换为C++ Exception

以下两段摘自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 handler
LPTOP_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 log
	UnhandledExceptionFilter(info);

	// now handle it internally
	Exception 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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值