 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
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;
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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>
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | 3.00/5 (2 votes) |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
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.
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
 |
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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);
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Specify please /EHa option for compiler (asynchronous exception handling model) and your exception has to be caught.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Martin,
I am in NY (not in Manhattan though) and got caught up watching the action today. It was pretty bad. One of my collegues have his son in the 8th grade. In his class alone, 5 of the kids had one of their parents killed in this tragedy.
Coming back, the problem was that the exception was occurring outside the try catch handler and so the translator was not catching that.
Thank you very much for taking the time to make a demo application and send it to me. I really appreciate that.
Regards
Thomas
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Tom,
it was really very bad, what's happened. When I saw it the first time I thought it is some movie, I could not believe it is real.
Thanks for your suggestion. You pointed me to review my code and I found out that compiler switch /EHa is required for VC++ 6, because of changed exception handling.
Kind regards,
Martin
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |