代码之家  ›  专栏  ›  技术社区  ›  tfinniga

获取有关在catch块中抛出c++异常的位置的信息?

  •  8
  • tfinniga  · 技术社区  · 16 年前

    我有一个c++应用程序,它将大部分代码封装在try块中。当我捕捉到异常时,我可以将用户返回到稳定状态,这很好。但我再也不会被撞车了。我很想找出代码中发生异常的地方,这样我就可以记录并修复它。

    是否有某种方法可以确定异常是从catch块中抛出的?如果有用的话,我在windowsxp和更高版本上使用原生msvc++。我的计划是简单地将崩溃记录到不同用户机器上的一个文件中,然后在崩溃日志达到一定大小后上传。

    5 回复  |  直到 16 年前
        1
  •  6
  •   Glorfindel Doug L.    5 年前

    这可以通过使用SEH(结构化异常处理)实现。关键在于MSVC通过SEH实现C++异常。另一方面,纯SEH更强大、更灵活。

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

    DoSomething 对于SEH区块:

    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
    }
    

    也就是说,在C++尝试/catch块中,我们放置了另一个原始SEH块,它只丢弃所有异常而不捕获它们。

    看到了吗 here

        2
  •  4
  •   John Dibling    16 年前

    可以将异常设计为包含源文件名;行号。为此,您需要创建一个派生自 std::exception 包含信息。在下面的示例中,我的应用程序有一个例外库,包括 my_exception . 我也有一个 traced_error 跟踪\u错误 what()

    #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;
    }
    

    该程序的输出为:

    文件:.\main.cpp行:57错误: 我的例外是什么

    您还可以重新设计它,以便应用程序级异常从 跟踪\u错误 相反,如果您更希望捕获特定的应用程序级异常,则可以使用另一种方法。在你的 catch MiniDumpWriteDump() .

        3
  •  2
  •   SigTerm    16 年前

    MiniDumpWriteDump 功能。

    如果你使用C++异常,那么你可以简单地包含文件/行/函数信息(如果你调用STD::Ext.

    如果您试图捕获操作系统异常,那么崩溃应用程序可能是更好的选择。

        4
  •  1
  •   jdehaan    16 年前

    您需要的是分析堆栈以找出异常的来源。对于msvc,有一个lib称为 dbghelp.dll 可以帮助您注销异常。一般来说,我做的是注销 minidump file and use this to replay the issue 除了使用正确的程序数据库(pdb文件)。这适用于没有源代码或您不想向其提供PDB的客户系统。

        5
  •  1
  •   Mark Ransom    16 年前

    独立于编译器的一个技巧是将throw语句包装到函数中。该函数可以在抛出异常之前执行其他任务,例如记录到日志文件。它还提供了一个放置断点的方便位置。如果创建宏来调用函数,则可以自动包含 __FILE__ __LINE__ 投掷发生的地方。