 |
|
 |
Hello Martin,
Could you please tell me under which license this code is covered? I'd like to use these files in a corporate application.
Thank you,
Jason
|
|
|
|
 |
|
 |
Martin,
great article. The _set_se_translator function is a very interesting thing, and I wrote some code like yours before I found your article. However I am unable to catch breakpoint exceptions (code 0x80000003; insert '__asm int 3' in your code to create). Windows keeps saying 'blah.exe has stopped to work' (or similar, I have German Vista). I don't know whether this is a peculiarity of Vista, or of VS2008, or just my failing to do it right
Hans
|
|
|
|
 |
|
 |
Hi,
I develop Windows Mobile applications (Visual Studio 2008, C++, MFC). I wanted to use try-catch for C++ exceptions and C++ wrapper class for SE exceptions, but for latest is not possible since _set_se_translator() is not available on WinCE. Then I thought to also catch SE with catch(...), but then I don't have information about SE exception (code, address,...). Is there any other way how to use C++ catch(?), where '?' means some type that would catch SE only? catch(UINT n) doesn't work, regardless that SE is exactly of that type. I read some posts though, that catch (unsigned int n) should also catch SEH, but it didn't work for me.
Any ideas, any workaround?
Thanks in advance,
Bostjan Erzen
|
|
|
|
 |
|
 |
Sorry to bother you on this forum but your e-mail address I have is not working, can you send me some where I can send you a message? Thanks a lot.
My address is: val_gornerova@yahoo.co.uk
Valca G.
|
|
|
|
 |
|
 |
Replacing the CASE macro as shown will provide the offending location and access type for EXCEPTION_ACCESS_INFORMATION, which is the only exception that currently has additional information available: #define CASE(nSeCode,CsString) case EXCEPTION_##nSeCode: \ if ( EXCEPTION_##nSeCode == EXCEPTION_ACCESS_VIOLATION ) \ { \ CsString.Format( _T("Exception %s (0x%.8X) at address 0x%.8X. %s 0x%.8X"), \ _T(#nSeCode),\ EXCEPTION_##nSeCode,\ m_pExcPointers->ExceptionRecord->ExceptionAddress, \ m_pExcPointers->ExceptionRecord->ExceptionInformation[0] ? _T("\r\nUnable to write location:") : _T("\r\nUnable to read location:"), \ m_pExcPointers->ExceptionRecord->ExceptionInformation[1] ); \ } \ else \ { \ CsString.Format(_T("Exception %s (0x%.8X) at address 0x%.8X."), \ _T(#nSeCode),\ EXCEPTION_##nSeCode,\ m_pExcPointers->ExceptionRecord->ExceptionAddress); \ } \ break;
|
|
|
|
 |
|
 |
In your try/catch handler, you need to check for noncontinuable exceptions, and exit your application if appropriate. <code> try { .... } catch(CSeException *e) { _EXCEPTION_POINTERS* ExPtr = e->GetSePointers(); if( (ExPtr->ExceptionRecord->ExceptionCode == EXCEPTION_NONCONTINUABLE_EXCEPTION) || (ExPtr->ExceptionRecord->ExceptionFlags == EXCEPTION_NONCONTINUABLE ) ) { ::PostMessage(AfxGetApp()->GetMainWnd()->GetSafeHwnd(), WM_QUIT, 0,0); } e->Delete(); } </code>
|
|
|
|
 |
|
 |
Works fine with Visual C++ .Net 2002 as well. However the asynchronous exception handling model must be enabled through compiler switch "/EHa" (like in VC6).
Why?
MSDN states "Use /EHa instead of /EHsc when using _set_se_translator.".
Practically, under VC7's default "Synchronous Exception Model" (compiler switch "/EHsc"), SEH exceptions are not always caught. In particular in Release mode because the compiler enables some optimizations.
For instance, the INT_DIVIDE_BY_ZERO exception is not caught when the following code is compiled in Release mode under VC7's default "Synchronous Exception Model" :
try {
int z = 0;
int n = 10 / z;
} catch(CSeException *e) {
TCHAR trcMsg[1024];
e->GetErrorMessage(trcMsg,1024);
TRACE(trcMsg);
TRACE(_T("\n"));
e->ReportError(MB_OK | MB_ICONSTOP);
e->Delete();
}
A very interresting article about this technical subject can be found here :
http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/
|
|
|
|
 |
|
 |
Hi! How can i catch a fp-exception as well with the provided class. In principle it should be possible, or? try { float a,b,c; a= 1.0; b= 0.0; c = a / b; } catch(...) { // got it? } Bye CptSpiff
|
|
|
|
 |
|
 |
Hi:
that are the only exceptions? Where can I to find all windows exceptions?
switch (m_nSeCode) {
CASE(ACCESS_VIOLATION,CsErrDescr);
CASE(DATATYPE_MISALIGNMENT,CsErrDescr);
CASE(BREAKPOINT,CsErrDescr);
CASE(SINGLE_STEP,CsErrDescr);
CASE(ARRAY_BOUNDS_EXCEEDED,CsErrDescr);
CASE(FLT_DENORMAL_OPERAND,CsErrDescr);
CASE(FLT_DIVIDE_BY_ZERO,CsErrDescr);
CASE(FLT_INEXACT_RESULT,CsErrDescr);
CASE(FLT_INVALID_OPERATION,CsErrDescr);
CASE(FLT_OVERFLOW,CsErrDescr);
CASE(FLT_STACK_CHECK,CsErrDescr);
CASE(FLT_UNDERFLOW,CsErrDescr);
CASE(INT_DIVIDE_BY_ZERO,CsErrDescr);
CASE(INT_OVERFLOW,CsErrDescr);
CASE(PRIV_INSTRUCTION,CsErrDescr);
CASE(IN_PAGE_ERROR,CsErrDescr);
CASE(ILLEGAL_INSTRUCTION,CsErrDescr);
CASE(NONCONTINUABLE_EXCEPTION,CsErrDescr);
CASE(STACK_OVERFLOW,CsErrDescr);
CASE(INVALID_DISPOSITION,CsErrDescr);
CASE(GUARD_PAGE,CsErrDescr);
CASE(INVALID_HANDLE,CsErrDescr);
default: CsErrDescr = _T("Unknown exception.");
thanks
|
|
|
|
 |
|
 |
They are listed in WinBase.h - I could be wrong, but that looks like it covers all of them!
|
|
|
|
 |
|
 |
I am sure that these are complete. Note that SEH exceptions are only CPU exceptions and don't refer to anything of the Windows stuff.
|
|
|
|
 |
|
 |
Hi Martin,
I was looking for something like this for a quite some time and somehow couldn't get original MSDN page. Well, that's even better I found your article! Looks like very neat thing to me.
I'm going to implement your idea with few variations to suit my code better. I was just wondering if there is any specific reason for creating new object in
void SeTranslator(UINT, _EXCEPTION_POINTERS*) ?
I didn't try anything yet, but I cannot see why cannot one just throw an object? Could you please share your point of view/reasons?
Thank you and best regards,
Holy Punk.
|
|
|
|
 |
|
 |
Hi,
if you want to use it with MFC, be aware that it catches exceptions by pointer, not by reference. If you throw an exception object instead of a pointer, it will not be caught in AfxCallWndProc() (in wincore.cpp).
If you install an exception handler try/catch, you are able to catch an exception by reference, but let's say you have this call stack:
MyFunc try/catch
SendMessage
AfxCallWndProc try/catch
int x = 5/0;
It is better not to let your C++ exception travel the call stack across Windows internal code and be caught in MyFunc, because of side effects of stack unwinding. AfxCallWndProc will catch exceptions derived from CException and pass them to the application/thread for processing. There you can display an error message. Yes, I don't like it either that they do it by pointer.
And also I don't like it that you cannot catch std::exception in AfxCallWndProc().
Mike
|
|
|
|
 |
|
 |
It works great in debug mode. I liked it so much I changed my 80k+ lines project to use it. But i'm getting weird results and strange bugs in release mode compiles. Yes I have the /EHa (asynchronous exception handlers) on in the options. The funny thing is when I turn off optimizations it works just great. Any reason for the strange bugs with optimizations on in release mode?
vc++ 6.0 sp5
The bug I found was that after calling bind() with port 0, getsockname didn't return the port that bind assigned my socket to listen on. works correctly in debug and release without optimizations. I also noticed that with debug info on in release mode, the variables had incorrect pointer address and values. eg a pointer would be 0x00 but I could step through just fine
|
|
|
|
 |
|
 |
I am happy you like my exception class and I would like to help you with solving troubles, however I cannot reproduce any strange behavioural. Can you please send me a sample code with described problems?
Kind regards,
Martin
|
|
|
|
 |
|
 |
Can we make CSeException class , MFC independent. Because we are deriving it from CException.
I think if we did it , then we can use this class in Win32-SDK also.
|
|
|
|
 |
|
 |
CSeException is extension to existing CException from MFC, however, when you will remove all the referencies to MFC from CSeException sources, then you will get CSeException class 'MFC independent' and you can use it in the 'SDK only' projects. Simply remove any reference to CException and delete method BOOL GetErrorMessage(CString & CsErrDescr, PUINT pnHelpContext = NULL);
|
|
|
|
 |
|
 |
I'm using win2k and xp thread pooling functions, is it ok to call _set_se_translator multiple times.. eg in the class constructor rather than at the start of the thread?
|
|
|
|
 |
|
 |
I see no problem to call this function multiple times, have a look in the MSDN for description:
_set_se_translator returns a pointer to the previous translator function registered by _set_se_translator, so that the previous function can be restored later. If no previous function has been set, the return value may be used to restore the default behaviour; this value may be NULL.
So, answer depends on your scenario, probably good idea would be to restore previous handle in your destructor.
|
|
|
|
 |
|
 |
can this class tell the exception type? if it can't how is it better than catch(...)?
|
|
|
|
 |
|
 |
Type of the SE exception is always int. You can catch it as int type, but then you have to decide on the value, which exception has occurred. My class does this for you - it can format a message with proper description of exception. And off course, you can catch C++ exception and SE exception with the same code. When you will use only catch(...) then you have no idea of what exception has been thrown.
|
|
|
|
 |
|
 |
When I do this in threads created using CreateThread, it does not come into the exception function. Is there something that I have to do extra? MSDN says that each thread has to register its own function. So I did it at the start of the thread procedure passed to the CreateThread.
Thanks in advance
Thomas
|
|
|
|
 |
|
 |
Specify please /EHa option for compiler (asynchronous exception handling model) and your exception has to be caught.
|
|
|
|
 |
|
 |
Thanks for the reply ...
but it still does not work.
What I am doing is:
_beginthreadex(NULL, 0, ThreadProc, this, 0, &nThreadId);
In ThreadProc
_set_se_translator(trans_func);
// code to create exception
When run, this never reaches the trans_func. Instead the access violation error comes up in the standard dialog box.
But the same thing works fine from the primary thread of the application.
Thank you
Thomas
|
|
|
|
 |
|
 |
I did something like this:
UINT WINAPI TestThread(LPVOID)
{
_set_se_translator(SeTranslator);
char *p = NULL;
try {
p[0] = 0;
} catch(CSeException *e) {
TCHAR trcMsg[1024];
e->GetErrorMessage(trcMsg,1024);
TRACE(trcMsg);
TRACE(_T("\n"));
e->ReportError(MB_OK | MB_ICONSTOP);
e->Delete();
}
return 0;
}
void CSehDemoDlg::OnThreadex()
{
UINT Id = 0;
_beginthreadex(NULL, 0, TestThread, this, 0, &Id);
}
and it is working fine. I sent you modified demo program (with changes above) by e-mail, please, have a look and compare it with your code. And let me know, what was different, please. Thanks.
|
|
|
|
 |