Getting information about where c++ exceptions are thrown inside of catch block?

后端 未结 5 1491
误落风尘
误落风尘 2020-12-13 23:02

I\'ve got a c++ app that wraps large parts of code in try blocks. When I catch exceptions I can return the user to a stable state, which is nice. But I\'m not longer recei

相关标签:
5条回答
  • 2020-12-13 23:31

    One trick that is compiler independent is to wrap the throw statement in a function. The function can perform other duties before throwing the exception, such as recording to a log file. It also makes a handy place to put a breakpoint. If you create a macro to call the function you can automatically include the __FILE__ and __LINE__ where the throw occurred.

    0 讨论(0)
  • 2020-12-13 23:42

    This is possible with using SEH (structured exception handling). The point is that MSVC implements C++ exceptions via SEH. On the other hand the pure SEH is much more powerful and flexible.

    That's what you should do. Instead of using pure C++ try/catch blocks like this:

    try
    {
        DoSomething();
    } catch(MyExc& exc)
    {
        // process the exception
    }
    

    You should wrap the inner code block DoSomething with the SEH block:

    void DoSomething()
    {
        __try {
            DoSomethingInner();
        }
        __except (DumpExc(GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH) {
            // never get there
        }
    }
    
    void DumpEx(EXCEPTION_POINTERS* pExc)
    {
        // Call MiniDumpWriteDump to produce the needed dump file
    }
    

    That is, inside the C++ try/catch block we place another raw SEH block, which only dumps all the exceptions without catching them.

    See here for an example of using MiniDumpWriteDump.

    0 讨论(0)
  • 2020-12-13 23:43

    You can write dumps using MiniDumpWriteDump function.

    If you're using C++ exceptions, then you can simply include file/line/function information (so you'll see it as text if you call std::exception.what()) in any place where you throw that exception (using ____FUNCTION____, ____FILE____ and ____LINE____ macros).

    If you're trying to catch OS exceptions, then crashing the application will be probably a better choice.

    0 讨论(0)
  • 2020-12-13 23:51

    What you need is to analyze the stack to figure out where the exception came from. For msvc there is a lib called dbghelp.dll that can help you log out the exceptions. In general what I do is to log out a minidump file and use this to replay the issue beside using the right program database (pdb file). This works on a customer systems that do not come with source code or to whom you won't want to give pdbs.

    0 讨论(0)
  • 2020-12-13 23:54

    It's possible to design your exceptions to include source file names & line numbers. In order to do so, you need to create a class derived from std::exception to contain the information. In the example below, I have a library of exceptions for my application including my_exception. I also have a traced_error which is a template exception class derived from my application-level exceptions. The traced_error exception holds information about the filename & line number, and calls the application-level exception class' what() method to get detailed error information.

    #include <cstdlib>
    #include <string>
    #include <stdexcept>
    #include <iostream>
    using namespace std;
    
    
    template<class EX>
    class traced_error : virtual public std::exception, virtual public EX
    {
    public:
        traced_error(const std::string& file, int line, const EX& ex)
        :   EX(ex),
            line_(line),
            file_(file)
        {       
        }
    
        const char* what() const
        {
            std::stringstream ss;
            static std::string msg;
            ss << "File: " << file_ << " Line: " << line_ << " Error: " << EX::what();
            msg = ss.str().c_str();
            return msg.c_str();
        }
    
        int line_;
        std::string file_;
    };
    
    template<class EX> traced_error<EX> make_traced_error(const std::string& file, int line, const EX& ex)
    {
        return traced_error<EX>(file, line, ex);
    }
    
    
    class my_exception : virtual public std::exception
    {
    public:
        my_exception() {};
    
        const char* what() const
        {
            return "my_exception's what";
        }
    };
    
    #define throwx(EX) (throw make_traced_error(__FILE__,__LINE__,EX))
    
    
    int main()
    {
        try
        {
            throwx(my_exception());
        }
        catch( const std::exception& ex )
        {
            cout << ex.what();
        }
        return 0;
    }
    

    The output of this program is:

    File: .\main.cpp Line: 57 Error: my_exception's what

    You could also redesign this so that the application-level exceptions derive from traced_error instead of the other way round, in case you would rather catch specific application-level exceptions. In your catch, you can log the error to a log file & create a dump file using MiniDumpWriteDump().

    0 讨论(0)
提交回复
热议问题