簡體   English   中英

與std :: error_code的錯誤堆棧

[英]Error stack with std::error_code

對於錯誤處理,異常對我來說是有問題的,因為我的代碼將是一個動態鏈接的庫。 此外,我認為例外情況只應在特殊情況下使用。 但是我會遇到可能發生錯誤但不例外的情況。 另一個問題是我的庫將從C#調用。 因此,對所有錯誤使用異常似乎不是正確的選擇。

但我發現std :: error_code和std :: error_category的概念非常令人愉快,並希望在我的應用程序中使用它。 但是,我還想為錯誤提供某種堆棧跟蹤。

考慮一個示例:用戶想要從數據庫加載域對象。 要加載此域對象,應用程序需要從不同的表加載行。 假設找不到其中一個必需的行。 在這種情況下,數據庫層將生成一些“未找到”錯誤。 如果我的所有傳播這個錯誤直到用戶因為沒有人知道發生什么沒有發現該錯誤信息不會是非常有益的。 同樣,如果每個層處理較低層的錯誤並生成相應的新錯誤,抽象出低級錯誤,我最終會得到類似“無法從數據庫加載”這樣的東西,這也不是很有用。 我想要的是兩者兼而有之。 也就是說,每個層都抽象出從任何較低級別獲得的錯誤,以便能夠向最終用戶顯示描述性消息,但同時我不想丟失有關低級別錯誤的信息。 所以我希望有類似錯誤堆棧跟蹤的東西。

我考慮從std :: error_code派生並使用指向底層std :: error_code的方法擴展該類,並使用方法來獲取所有這些底層對象。 但是,我不確定這種技術是不是一個好主意,因為我讀到在設計std :: error_code以使其高效時需要小心。

我們希望error_code是一個值類型,可以在不進行切片的情況下進行復制,也不需要堆分配,但我們也希望它具有基於錯誤類別的多態行為。

編輯我現在認為這種技術也會引入切片問題,不是嗎?

編輯2我現在想通過從std :: error_code派生來實現它。 而不是指針,什么需要在某處進行堆分配,我的派生類將有一個boost :: optional。 這樣,只需復制內部錯誤代碼就可以在堆棧上創建內部錯誤代碼。 一個不存在的內部錯誤代碼可以正確地由boost :: optional表示。 切片仍然是一個問題,但我想這是可以忽略的,因為將我的派生類的實例分配給std :: error_code變量的情況不是必要的,即使它發生了,我也只會丟失有關內部錯誤代碼的信息。 此外,我可以提供從std :: error_code到我沒有內部錯誤代碼的派生類的轉換。

編輯3我沒想到讓一個包含boost :: optional本身的類是不可能的。 所以現在我沒有看到沒有在堆上分配我想要的東西的任何可能性。

最后我是從std::error_code派生的。 我的派生類有一個成員,它是指向同一個類的實例的指針。 我向該類添加了一個wrap()方法,該方法接受與該參數相同的類的實例,並在堆上分配它的副本。 派生類的析構函數確保再次釋放內存。 我也為這個內部錯誤代碼添加了一個getter方法。 這樣我可以堆疊幾個錯誤代碼。 缺點是,我需要堆分配,但我只是希望,在我的場景中,這不會導致重大的性能問題。 我的類還提供了從std::error_code轉換。


class my_error : public std::error_code
{
public:
    my_error() : std::error_code(), m_innerError(NULL) {};
    my_error( int val, const std::error_category & cat ) : std::error_code(val, cat), m_innerError(NULL) {};
    my_error( std::error_code & error ) : std::error_code(error), m_innerError(NULL) {};
    my_error( const std::error_code & error ) : std::error_code(error), m_innerError(NULL) {};
    ~my_error()
    {
        delete m_innerError;
    }

    template <class ErrorCodeEnum>
    my_error(ErrorCodeEnum e,
                   typename boost::enable_if<std::is_error_code_enum<ErrorCodeEnum> >::type* = 0)
    {
        *this = make_custom_error(e);
    }

    template<typename ErrorCodeEnum>
    typename boost::enable_if<std::is_error_code_enum<ErrorCodeEnum>, error_code>::type &
    operator=( ErrorCodeEnum val )
    {
        *this = make_custom_error(val);
        return *this;
    }

    my_error const * get_inner() const
    {
        return m_innerError;
    };

    void wrap( const my_error & error)
    {
        m_innerError = new my_error(error);
    };

private:
    my_error * m_innerError;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM