ROWANBRIGHTON
asked on
Getting specific error message from C++ catch()
I'm trying to catch a meaningful error message when an exception is thrown.
When the exception is caught by MFC TRY-CATCH statement, I can retrieve an error message with not problem.
But when it's thrown by non-MFC code, that's when I have the problem.
The reason I'm trying to get a specific error message is because when my code interfaces with a third party DLL, it throws an exception.
Since I have no documents for the DLL, I'm not sure what it's throwing, and it's not being caught by the MFC CATCH_ALL block.
How can I get details of the object being thrown on a C++ catch() statement?
This code is an example of an exception that is not caught by MFC CATCH_ALL.
void main()
{
char* s = NULL;
int* p = NULL;
TRY
{
try
{
s = new char[10];
*p = 5;
}
catch(...)
{
printf("Got Unknown error\n");
}
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL
delete[] s;
}
When the exception is caught by MFC TRY-CATCH statement, I can retrieve an error message with not problem.
But when it's thrown by non-MFC code, that's when I have the problem.
The reason I'm trying to get a specific error message is because when my code interfaces with a third party DLL, it throws an exception.
Since I have no documents for the DLL, I'm not sure what it's throwing, and it's not being caught by the MFC CATCH_ALL block.
How can I get details of the object being thrown on a C++ catch() statement?
This code is an example of an exception that is not caught by MFC CATCH_ALL.
void main()
{
char* s = NULL;
int* p = NULL;
TRY
{
try
{
s = new char[10];
*p = 5;
}
catch(...)
{
printf("Got Unknown error\n");
}
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL
delete[] s;
}
Hmm, first thing is why are you using the expired TRY CATCH macros of MFC ? You should be using the classic C++ try / catch mechanism...
Ignore comment above; sorry :)
On second thought, you could always get error information from GetLastError() - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/retrieving_the_last_error_code.asp - that brings up what caused the problem regardless of MFC or not...
ASKER
>>could always get error information from GetLastError()
That's the first thing I tried, and it bring back zero, as if no errors.
{
char* s = NULL;
int* p = NULL;
TRY
{
try
{
s = new char[10];
*p = 5;
}
catch(...)
{
printf("Last Error = %i\n", GetLastError());
}
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL
delete[] s;
That's the first thing I tried, and it bring back zero, as if no errors.
{
char* s = NULL;
int* p = NULL;
TRY
{
try
{
s = new char[10];
*p = 5;
}
catch(...)
{
printf("Last Error = %i\n", GetLastError());
}
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL
delete[] s;
ASKER
>>that brings up what caused the problem regardless of MFC or not...
If you run the above code, you'll see that it doesn't bring back the last error.
I believe GetLastError only works with other WINDOWS API functions.
If you run the above code, you'll see that it doesn't bring back the last error.
I believe GetLastError only works with other WINDOWS API functions.
ASKER
char* s = NULL;
int* p = NULL;
TRY
{
try
{
s = new char[10];
*p = 5;
}
catch(...)
{
int e1 = errno;
int e2 = _doserrno;
int e3 = GetLastError();
printf("Last errno = %i\n", e1);
printf("Last _doserrno = %i\n", e2);
printf("Last GetLastError = %i\n", e3);
}
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL
delete[] s;
int* p = NULL;
TRY
{
try
{
s = new char[10];
*p = 5;
}
catch(...)
{
int e1 = errno;
int e2 = _doserrno;
int e3 = GetLastError();
printf("Last errno = %i\n", e1);
printf("Last _doserrno = %i\n", e2);
printf("Last GetLastError = %i\n", e3);
}
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL
delete[] s;
>> *p = 5;
I think that that is a bad example of getting an exception to be thrown anyway. Have you tried with a simple C++ class that throws an exception per-se ?
I think that that is a bad example of getting an exception to be thrown anyway. Have you tried with a simple C++ class that throws an exception per-se ?
ASKER
>>I think that that is a bad example of getting an exception to be thrown anyway. Have you tried with a simple C++ class that throws an exception per-se ?
On my project the exception is being thrown from a DLL.
I don't have controle of the DLL or it's code.
I posted the above code as an example because I get the same exact results when I try to catch the exception from the DLL as I do with the code I posted.
So modifying the example is not going to help me solve my problem.
I need a method that can determine what is being thrown or some type of error message that has any details of the exception.
On my project the exception is being thrown from a DLL.
I don't have controle of the DLL or it's code.
I posted the above code as an example because I get the same exact results when I try to catch the exception from the DLL as I do with the code I posted.
So modifying the example is not going to help me solve my problem.
I need a method that can determine what is being thrown or some type of error message that has any details of the exception.
Unless I'm mistaken and CATCH_ALL catches this, I think that interrupts (such as division by zero, for example) are thrown as ints. So maybe you can try to try .. catch (int n) and see what happens.
ASKER
>>Unless I'm mistaken and CATCH_ALL catches this, I think that interrupts (such as division by zero, for example) are thrown as ints. So maybe you can try to try ..
>>catch (int n) and see what happens.
It doesn't. If it could catch it, then it would enter into the CATCH_ALL block, which it is not.
Run above code for test, and you'll see.
I also tried catching with int, char, char*, and a few other types.
None of them cought the exception.
>>catch (int n) and see what happens.
It doesn't. If it could catch it, then it would enter into the CATCH_ALL block, which it is not.
Run above code for test, and you'll see.
I also tried catching with int, char, char*, and a few other types.
None of them cought the exception.
Might be a long shot, but you could try using Managed C++ for handling the exception - http://www.codeproject.com/managedcpp/ExceManagedcpp.asp
That has built in methods for displaying info,
That has built in methods for displaying info,
Have you set the /EHa compiler option?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
BTW, see also the VC++ docs about '_set_se_translator()' on how to turn these SEX exceptions into C++ excptions: http://msdn.microsoft.com/library/en-us/vclib/html/_crt__set_se_translator.asp
ASKER
>>Are you sure it is not a SEH exception?
If it is a SEH exception, how can I used this in conjunction with MFC TRY-CATCH?
I have my project setup so it first tries to capture the exception using MFC TRY-CATCH, because the MFC exception gives me the most information for cause of error.
I need a method that can capture any exceptions not caught by CATCH_ALL(e)
If you look at test1b function, you'll see that the C++ catch(...) is able to capture anything that CATCH_ALL can not.
The problem is I get no meaningfull information about the exception.
void test1b()
{
char* s = NULL;
int* p = NULL;
try
{
TRY
{
s = new char[10];
*p = 5;
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL
}
catch(...)
{
int e1 = errno;
int e2 = _doserrno;
int e3 = GetLastError();
int e4 = _sys_nerr;
printf("Last errno = %i\n", e1);
printf("Last _doserrno = %i\n", e2);
printf("Last GetLastError = %i\n", e3);
printf("Last _sys_errlist = %s\n", _sys_errlist[e4]);
}
delete[] s;
}
When I try the same approach with SEH exception, I get a compile error.
If it is a SEH exception, how can I used this in conjunction with MFC TRY-CATCH?
I have my project setup so it first tries to capture the exception using MFC TRY-CATCH, because the MFC exception gives me the most information for cause of error.
I need a method that can capture any exceptions not caught by CATCH_ALL(e)
If you look at test1b function, you'll see that the C++ catch(...) is able to capture anything that CATCH_ALL can not.
The problem is I get no meaningfull information about the exception.
void test1b()
{
char* s = NULL;
int* p = NULL;
try
{
TRY
{
s = new char[10];
*p = 5;
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL
}
catch(...)
{
int e1 = errno;
int e2 = _doserrno;
int e3 = GetLastError();
int e4 = _sys_nerr;
printf("Last errno = %i\n", e1);
printf("Last _doserrno = %i\n", e2);
printf("Last GetLastError = %i\n", e3);
printf("Last _sys_errlist = %s\n", _sys_errlist[e4]);
}
delete[] s;
}
When I try the same approach with SEH exception, I get a compile error.
ASKER
error C2713: Only one form of exception handling permitted per function
error C2712: Cannot use __try in functions that require object unwinding
I get those compile errors for the code below:
void testca()
{
char* s = NULL;
int* p = NULL;
TRY
{
__try
{
s = new char[10];
*p = 5;
}
__except(1)
{
printf("Caught SEH exception = %0x8.8x\n", GetExceptionCode());
}
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL;
delete[] s;
}
error C2712: Cannot use __try in functions that require object unwinding
I get those compile errors for the code below:
void testca()
{
char* s = NULL;
int* p = NULL;
TRY
{
__try
{
s = new char[10];
*p = 5;
}
__except(1)
{
printf("Caught SEH exception = %0x8.8x\n", GetExceptionCode());
}
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL;
delete[] s;
}
ASKER
I get same errors for this code too....
void test1a()
{
char* s = NULL;
int* p = NULL;
__try
{
TRY
{
s = new char[10];
*p = 5;
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL;
}
__except(1)
{
printf("Caught SEH exception = %0x8.8x\n", GetExceptionCode());
}
delete[] s;
}
void test1a()
{
char* s = NULL;
int* p = NULL;
__try
{
TRY
{
s = new char[10];
*p = 5;
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL;
}
__except(1)
{
printf("Caught SEH exception = %0x8.8x\n", GetExceptionCode());
}
delete[] s;
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
On my machine, using VC++ 6 SP6, with compiler options /nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/TestException.pc h" /Yu"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
the following program:
#include "stdafx.h"
int main(int argc, char* argv[])
{
char* s;
int* p = NULL;
try
{
s = new char[10];
*p = 5;
}
catch(...)
{
printf("Got Unknown error\n");
}
delete[] s;
}
Produces:
Got Unknown error
the following program:
#include "stdafx.h"
int main(int argc, char* argv[])
{
char* s;
int* p = NULL;
try
{
s = new char[10];
*p = 5;
}
catch(...)
{
printf("Got Unknown error\n");
}
delete[] s;
}
Produces:
Got Unknown error
ASKER
Nievergelt,
I'm not having a problem catching it in the C++ catch(...)
The problem is that I'm not getting a specific error message, exception type, or error number.
I'm not having a problem catching it in the C++ catch(...)
The problem is that I'm not getting a specific error message, exception type, or error number.
ASKER
>>georg74,
I already thought about that as a work around, but that will require me to make a lot of code changes.
I'll have to add a bunch of extra functions. And if I have a functions that has multiple TRY-CATCH_ALL, I will not be able to tell which block threw the exception.
I already thought about that as a work around, but that will require me to make a lot of code changes.
I'll have to add a bunch of extra functions. And if I have a functions that has multiple TRY-CATCH_ALL, I will not be able to tell which block threw the exception.
since CPU/OS exception should not happen often, you can catch them
in the "main" function, or at similar appropriate place. I assume you want
to store "error report" and exit nicely even if your code produces a GPF or DIV0.
> I will not be able to tell which block threw the exception
to know which block it was, but not to have to split a lot of functions to
separate exception handling forms, you can follow one of these ways:
- use a global singleton class dbg_ctx, which will store the description
of the current block. this can be a simple string or a list. example:
class dbg_ctx
{
public:
static enter(const char *); // store (add) context description
static leave(); // remove context description
static string context;
};
...
try {
dbg_ctx::enter("this block of code");
... do something ...
dbg_ctx::leave();
}
catch (exception &e) {
...
}
in the (outer) SEH, you then use dbg_ctx::context when generating
error message.
- write your own exception handler as described in the given article. complicated.
- include some debugger functionality. even more complicated.
hth,
georg
in the "main" function, or at similar appropriate place. I assume you want
to store "error report" and exit nicely even if your code produces a GPF or DIV0.
> I will not be able to tell which block threw the exception
to know which block it was, but not to have to split a lot of functions to
separate exception handling forms, you can follow one of these ways:
- use a global singleton class dbg_ctx, which will store the description
of the current block. this can be a simple string or a list. example:
class dbg_ctx
{
public:
static enter(const char *); // store (add) context description
static leave(); // remove context description
static string context;
};
...
try {
dbg_ctx::enter("this block of code");
... do something ...
dbg_ctx::leave();
}
catch (exception &e) {
...
}
in the (outer) SEH, you then use dbg_ctx::context when generating
error message.
- write your own exception handler as described in the given article. complicated.
- include some debugger functionality. even more complicated.
hth,
georg
>>If it is a SEH exception, how can I used this in conjunction with MFC TRY-CATCH?
Because these are stwo unrelated exception handling mechanisms that do not "know" of each other - unless you provide a translator function as described in http://msdn.microsoft.com/library/en-us/vclib/html/_crt__set_se_translator.asp ("_set_se_translator()")
Because these are stwo unrelated exception handling mechanisms that do not "know" of each other - unless you provide a translator function as described in http://msdn.microsoft.com/library/en-us/vclib/html/_crt__set_se_translator.asp ("_set_se_translator()")
The problem is that you are declaring an int *, not giving it any memory, and trying to dereference the pointer. You need to allocate the int * at some point:
int* p = NULL;
...
p = new int;
...
*p = 5;
int* p = NULL;
...
p = new int;
...
*p = 5;
ASKER
mnashadka,
>>The problem is that you are declaring an int *, not giving it any memory
Of course. LOL
Did you not read the entire question?
Please read the entire question.
>>The problem is that you are declaring an int *, not giving it any memory
Of course. LOL
Did you not read the entire question?
Please read the entire question.
ASKER
>>Because these are stwo unrelated exception handling mechanisms that do not "know" of each other -
I'm not trying to get them to know about each other. I just need them to be able to work side by side in the same function.
I'm not trying to get them to know about each other. I just need them to be able to work side by side in the same function.
ASKER
I decided to use a combination of the three excpetion methods.
std::string glb_LastError;
void test1()
{
char* s = NULL;
int* p = NULL;
try
{
TRY
{
s = new char[10];
*p = 5;
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL;
}
catch(...)
{
glb_LastError = "test1";
throw;
}
delete[] s;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
__try
{
test1();
}
__except(1)
{
printf("Caught SEH exception = %8.8x\n", GetExceptionCode());
printf("Exception occurred at %s\n", glb_LastError.c_str());
}
std::string glb_LastError;
void test1()
{
char* s = NULL;
int* p = NULL;
try
{
TRY
{
s = new char[10];
*p = 5;
}
CATCH_ALL(Ex)
{
Ex->ReportError();
}
END_CATCH_ALL;
}
catch(...)
{
glb_LastError = "test1";
throw;
}
delete[] s;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
__try
{
test1();
}
__except(1)
{
printf("Caught SEH exception = %8.8x\n", GetExceptionCode());
printf("Exception occurred at %s\n", glb_LastError.c_str());
}
>> I decided to use a combination of the three excpetion methods
Just in case I have not mentioned this *g* - I'd use a translator as described in http://msdn.microsoft.com/library/en-us/vclib/html/_crt__set_se_translator.asp ("_set_se_translator()")
Just in case I have not mentioned this *g* - I'd use a translator as described in http://msdn.microsoft.com/library/en-us/vclib/html/_crt__set_se_translator.asp ("_set_se_translator()")