6

Good Morning!

Edit: This is not a duplicate as it specifically pertains to SEH, not code-level thrown exceptions.

I'm using SEH to catch hardware errors thrown by some unreliable libraries. I'd like to get more information from the catchall exception. The following code simulates what I'm doing. As you can see, I'm using boost's current_exception_diagnostic_information, but it just spits out "No diagnostic information available." - not terribly helpful.

Is it possible to, at a minimum, get the termination code that would have been returned had the exception not have been caught? (In this case 0xC0000005, Access Violation)

#include "stdafx.h"
#include <future>
#include <iostream>
#include <boost/exception/diagnostic_information.hpp>

int slowTask()
{
    //simulates a dodgy bit of code
    int* a = new int[5]();
    a[9000009] = 3;
    std::cout << a[9000009];
    return 0;
}

int main()
{
    {
        try
        {
            std::future<int> result(std::async(slowTask));
            std::cout<< result.get();
        }
        catch(...)
        {
            std::cout << "Something has gone dreadfully wrong:"
                << boost::current_exception_diagnostic_information()
                << ":That's all I know."
                << std::endl;
        }           
    }

    return 0;
}
MSalters
  • 173,980
  • 10
  • 155
  • 350
Carbon
  • 3,828
  • 3
  • 24
  • 51
  • 1
    If you're actually using SEH, you can [get the exception code](https://msdn.microsoft.com/en-us/library/ms679356.aspx). But you shouldn't really be catching these types of exceptions (things like null pointer exceptions, invalid memory address exceptions, etc.). – Cody Gray - on strike May 05 '17 at 13:11
  • Cody Gray: I know man and I feel kinda bad about it too. As soon as I get the time available, I'm gonna fix it properly, but such is life. – Carbon May 05 '17 at 13:16
  • 2
    `C0000005` is indeed SEH. Retagged & reopened. – MSalters May 05 '17 at 14:05
  • Thankye sir! Look fwd to hearing on this one. – Carbon May 05 '17 at 14:12

1 Answers1

11

Using catch (...) you get no information at all, whether about C++ exceptions or SEH. So global handlers are not the solution.

However, you can get SEH information through a C++ exception handler (catch), as long as you also use set_se_translator(). The type of the catch should match the C++ exception built and thrown inside your translator.

The function that you write must be a native-compiled function (not compiled with /clr). It must take an unsigned integer and a pointer to a Win32 _EXCEPTION_POINTERS structure as arguments. The arguments are the return values of calls to the Win32 API GetExceptionCode and GetExceptionInformation functions, respectively.

Or you can use __try/__except, which are specific to SEH. They can be used inside C++ just fine, including in programs where C++ exceptions are used, as long as you don't have SEH __try and C++ try in the same function (to trap both types of exceptions in the same block, use a helper function).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • That did it. I also used the sample code from the link you provided, https://msdn.microsoft.com/en-us/library/5z4bw5h5.aspx, the whole thing works great. – Carbon May 05 '17 at 14:26
  • @Ben Voigt: How would you design the helper functions to handle both types? I've been racking my brain about this for 6 hours, but I just can't figure out how to pass on "real" exceptions and catch SEH exceptions (with valid stack trace to the error instead of the handling code). We have a native DLL called from CLR, which should pass on any exceptions to the top C# layer. – AzP Sep 12 '18 at 07:52
  • 1
    @AzP: I never said you could build a .NET exception stack trace from the information, in fact the quote for a translator explicitly excludes C++/CLI. You can catch both SEH and C++ exceptions in C++ by using two functions, one with `try/catch` one with `__try/__except`. And you can extract the exception information. You can use native functions to get a stack trace (not easy, but plenty of examples around). Unfortunately you can't stuff that into a .NET exception, because .NET doesn't provide a setter for the stack trace. – Ben Voigt Sep 12 '18 at 13:11
  • @BenVoigt: Thanks, I've managed to figure out a solution to it now, following your link. I mistakenly only registered the translation function during the first invocation of the DLL, resulting in only translating/catching the SEHExceptions within that specific DLL. – AzP Sep 12 '18 at 13:18
  • @AzP: Glad to hear you got things working to your satisfaction. – Ben Voigt Sep 12 '18 at 13:19