Debug:深入查看Inner Exception

Debug:深入查看Inner Exception

在軟件開發過程中,我們經常會遇到異常情況。當異常發生時,了解異常的詳細信息和它的內部異常(Inner Exception)是非常重要的。內部異常提供了異常鏈中更深層次的上下文,幫助我們更好地理解和解決問題。本文將介紹一種方法,通過使用DeepLogInvocationException函數,可以方便地記錄並查看異常鏈中每個內部異常的詳細信息。

在Unity 2021.2.0a11版本中,我們可以利用其特性,直接在Unity3D控制台中打開與異常相關的文件,並跳轉到異常發生的行號。這為我們調試異常提供了便利。

首先,我們來看一下Hyperlink函數的實現。它是一個擴展方法,用於將文本標記為超鏈接並提供鏈接地址。在我們的方法中,我們使用了兩個重載:

public static string Hyperlink(this string tag, string url)
{
    return $"<a href=\"{url}\">{tag}</a>";
}

public static string Hyperlink(this string tag, string url, int line)
{
    return $"<a href=\"{url}\" line=\"{line}\">{tag}</a>";
}

接下来,让我们看一下DeepLogInvocationException函数的实现。它是一个扩展方法,用于在事件调度过程中调试异常。

public static void DeepLogInvocationException(this Exception ex, string delegateName, int skipDepth = 0)
{
    int skip = Mathf.Max(0, skipDepth);
    int atLeastOne = 0;
    StringBuilder sb = new StringBuilder();
    Exception orgEx = ex;
    while (ex is not null)
    {
        StackTrace trace = new(ex, true);

        if (skip <= 0)
        {
            var errorType   = ex.GetType().Name;
            for (var i = 0; i < trace.FrameCount; ++i)
            {
                if (TryGetFrameInfo(trace.GetFrame(i), out var info))
                {
                    sb.AppendLine(info);
                }
            }

            AxDebug.LogError($"[{delegateName}] -> {errorType}:\n{ex.Message}\n{sb.ToString()}\n\n{ex.StackTrace}\n");
            ++atLeastOne;
        }
        --skip;
        ex = ex.InnerException;
    }

    // Fall back when no exception was logged
    if (atLeastOne == 0)
        AxDebug.LogError($"Exception during {delegateName} < {orgEx.Message}\n{orgEx.StackTrace}\n");


    bool TryGetFrameInfo(StackFrame frame, out string info)
    {
        info = null;
        if (frame == null)
            return false;
        var filePath    = frame.GetFileName();
        if (filePath == null || filePath.Length == 0)
            return false;
        var fileName    = System.IO.Path.GetFileName(filePath);
        var lineNo      = frame.GetFileLineNumber();
        var methodName  = frame.GetMethod().GetFullName();
        var tag         = $"{fileName} > {methodName}";
        info = $"{tag.Hyperlink(filePath, lineNo)}:Line {lineNo}";
        return true;
    }
}

 

使用上述處理方式的好處和壞處如下:

好處:

詳細的異常信息:DeepLogInvocationException函數允許記錄異常鏈中每個內部異常的詳細信息,包括異常類型、消息和堆棧跟蹤。這樣可以提供更豐富的調試信息,幫助開發人員定位和解決問題。

異常調試的便利性:通過在Unity3D控制台中打開與異常相關的文件並跳轉到異常發生的行號,我們可以更方便地調試異常。這在復雜的代碼邏輯中特別有用,可以減少手動查找和追蹤異常的工作量。

內部異常的處理:異常鏈中的內部異常提供了更深層次的上下文信息,幫助我們了解異常的原因和發生位置。通過記錄並處理內部異常,我們可以更好地追蹤異常的源頭,並采取適當的措施進行修復。

壞處:

信息重復輸出:如果異常鏈較長且有多個內部異常,可能會導致重復輸出相同的異常信息。這可能會在日志中產生冗余信息,增加日志文件的大小。

可能影響性能:在遍歷異常鏈並記錄異常信息時,可能會引入一定的性能開銷。特別是在異常鏈較長或異常處理頻繁的情況下,可能會對應用程序的性能產生輕微影響。

綜上所述,使用DeepLogInvocationException函數可以提供更豐富的調試信息和異常處理能力,但需要注意避免冗余輸出和可能的性能影響。在開發過程中,根據具體情況和需求,可以權衡利弊並進行適當的使用和調整。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

*

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料