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;
}
ROWANBRIGHTONAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mrwad99Commented:
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...
0
mrwad99Commented:
Ignore comment above; sorry :)
0
mrwad99Commented:
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...
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

ROWANBRIGHTONAuthor Commented:
>>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;
0
ROWANBRIGHTONAuthor Commented:
>>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.
0
ROWANBRIGHTONAuthor Commented:
     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;
0
mrwad99Commented:
>> *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 ?
0
ROWANBRIGHTONAuthor Commented:
>>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.
0
aviadbdCommented:

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.

0
ROWANBRIGHTONAuthor Commented:
>>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.
0
mrwad99Commented:
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,
0
NievergeltSenior SW DevCommented:
Have you set the /EHa compiler option?
0
jkrCommented:
Are you sure it is not a SEH exception? A NULL pointer assignement like above definitely is. You could check that using

    char* s = NULL;
    int* p = NULL;
 
         __try
         {
              s = new char[10];
              *p = 5;
         }
         __except(1)
         {
               printf("Caught SEH exception = %0x8.8x\n", GetExceptionCode());
         }
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jkrCommented:
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
0
ROWANBRIGHTONAuthor Commented:
>>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.
0
ROWANBRIGHTONAuthor Commented:
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;
}
0
ROWANBRIGHTONAuthor Commented:
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;
}
0
georg74Commented:
hi ROWANBRIGHTON,

> I'm trying to catch a meaningful error message when an exception is thrown.

if it is a C++ exception you have to know the type of the object thrown.
in standard C++, there is a class exception used as a base class for
C++ exceptions. it has a method "const char * what()" that gives you the
(more or less) meaningful message.

if it is a system (CPU) exception on win32, like GPF or DIV0, then you're
using win32 SEH (Structured Exception Handling).
you can find details here: http://www.microsoft.com/msj/0197/exception/exception.aspx

in your code, separate the function into two. catch C++ exceptions in the inner one
and system exceptions in the outer one:

void testca_inner()
{
     char* s = NULL;
     int* p = NULL;
     TRY
     {
           s = new char[10];
           *p = 5;
     }
     CATCH_ALL(Ex)
     {
          Ex->ReportError();
     }
     END_CATCH_ALL;
     if (s)
          delete[] s;
}


void testca()
{
     __try
     {
          testca_inner();
     }
     __except(1)
     {
          printf("Caught SEH exception = %0x8.8x\n", GetExceptionCode());
     }
}

gl,
georg
0
NievergeltSenior SW DevCommented:
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.pch" /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

0
ROWANBRIGHTONAuthor Commented:
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.
0
ROWANBRIGHTONAuthor Commented:
>>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.

0
georg74Commented:
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
0
jkrCommented:
>>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()")
0
mnashadkaCommented:
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;
0
ROWANBRIGHTONAuthor Commented:
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.
0
ROWANBRIGHTONAuthor Commented:
>>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.
0
ROWANBRIGHTONAuthor Commented:
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());
      }
0
jkrCommented:
>> 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()")
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.