Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1015
  • Last Modified:

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;
}
0
ROWANBRIGHTON
Asked:
ROWANBRIGHTON
  • 13
  • 5
  • 4
  • +4
2 Solutions
 
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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
 
NievergeltCommented:
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
 
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
 
NievergeltCommented:
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

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 13
  • 5
  • 4
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now