2014-09-29 29 views
0

我工作的一個項目,我們有幾個共同的目標文件的幾個可執行文件。我們希望將日誌記錄添加到所有可執行文件中,並且有一個庫用於執行此操作。重寫對main()的調用?

然而,它似乎笨拙去到每一個可執行文件的main()功能,在同一個樣板函數調用添加到開始記錄。這意味着我們再次寫同樣的東西,並放棄可維護性和DRY(「不要重複自己」)。如果我們可以系統地確保在主函數被調用之前啓動日誌記錄,那將會很好。

我突然有libc中++函數進行調用爲主,並有可能超越它們。但是,我不知道它們是什麼,並且想象如果我們不小心,這可能會破壞事物。有誰知道這將如何完成?或者,如果這太過分了,還有關於如何繼續的其他建議?

我們使用C++ 11的g ++ 4.8,如果這有什麼差別。

+0

你爲什麼不「注入」到一個全局變量的構造函數/析構函數的啓動和關閉代碼?你留下的唯一問題是你多次這樣做;那麼它們被初始化的順序就沒有被指定,所以你不應該依賴任何。 – leemes 2014-09-29 08:45:12

+0

如何覆蓋每個可執行文件中的主函數比在每個可執行文件中向main添加一個函數調用更容易維護? – user2079303 2014-09-29 08:47:18

+0

這不是重複的。他沒有問過「我如何獲得代碼在main之前運行」?他已經問過如何解決問題,哪裏可能是解決方案的一部分。 – CashCow 2014-09-29 08:56:15

回答

5

你不需要通過修改main().

就應該在一個共享對象庫中創建在全局範圍內一個類來做到這一點。這個類的構造函數將在main()運行之前執行您想要執行的「初始化」,並且其析構函數將在main()之後運行。

你需要處理的問題是,這種初始化和破壞的順序是不能保證確定性至於其他任何全球範圍的對象。所有這些可以在一個.cpp編譯單元中進行。

class LoggingManager // you can make this a singleton but not necessary 
{ 
    public: 
     LoggingManager(); 

     ~LoggingManager(); 
}; 

LoggingManager::LoggingManager() 
{ 
    // your initialisation code goes here 
} 

LoggingManager::~LoggingManager() 
{ 
    // your clean-up code goes here. It should not throw 
} 

LoggingManager loggingManagerStaticInstance; 

注意這裏是「靜態變量初始化」問題的一小危險,這意味着在現實中你可能loggingManagerStaticInstance不會加載,直到你的編譯單元首次訪問。

實際上,如果這是在main()之後,只要初始化在第一次需要之前發生(有點像單例),但這意味着您的編譯單元可能需要包含可保證獲得的東西拉入英寸

如果你想「粘」到GNU或類似的,他們提供__attribute__(constructor)可能會解決它,雖然有一個更簡單的方法有一些虛擬外部int實現或虛函數返回一個int從內部調用無論您實際使用哪種標頭來實現日誌記錄。

+0

我現在抱着我的失望,但我相信這是不正確的。全局對象是在調用其翻譯單元的第一個函數之前一段時間創建的。這可能會在調用'main'之後。 – MSalters 2014-09-29 11:53:33

+0

我喜歡它! @MSalters這是很好的知道。我不一定需要開始記錄_before_ main被調用;只要我跟蹤編寫單位的全局對象,並確保我們在開始時調用某些東西,那麼我們應該是好的,對吧? – bchurchill 2014-09-30 07:47:59

+0

@bchurchill:是的,但通常有一種更好的(不太脆弱的)方法:在getLogger()方法中將記錄器設置爲靜態變量,該方法返回對其的引用。當第一次需要時,它會構建記錄器。 – MSalters 2014-09-30 07:55:39