2013-01-07 73 views
2

我正在研究一個C++應用程序,它使用另一個團隊用C編寫的庫。當發生錯誤時,庫的編寫者喜歡調用exit(),這會在不調用C++應用程序中堆棧上的對象的析構函數的情況下立即結束程序。應用程序設置了一些系統資源,這些資源在進程結束後不會自動被操作系統回收(共享內存區域,進程間互斥等),所以這是一個問題。如何處理第三方庫代碼中的exit()調用?

我有完整的應用程序和庫的源代碼,但該庫是非常完善的,並沒有單元測試,所以改變它將是一件大事。有沒有辦法將電話「掛鉤」到exit(),以便我可以實現我的應用程序的正常關機?這意味着所有的清理會發生無論是在其析構函數或者其成員之一的析構函數 - - 然後分配在這些大的一個對象,我考慮是使一個大的類應用

一種可能性堆在main(),設置一個全局指針指向它,並使用atexit()來註冊一個處理程序,它只是通過全局指針刪除對象。這可能有用嗎?

有沒有一種已知的方法可以解決這個問題?

回答

3

在最糟糕的情況下,您總是可以編寫自己的實現exit並鏈接它而不是系統自己的實現。您可以在那裏處理錯誤,並可以自己撥打_exit(2)

由於您擁有圖書館資源,因此更容易 - 只需在構建它時添加-Dexit=myExit標誌,然後提供myExit的實施。

+0

啊哈!在編譯C庫時,C++應用程序的makefile可以重新定義'exit' - 根本不需要修改代碼。我仍然需要實現從全局處理程序清理整個應用程序的能力,但仍然是迄今爲止最好的答案。 – bythescruff

3

安裝退出處理與atexit和實施所需的行爲

+0

我的確想到了這個(這是在問題中)。問題在於調用堆棧中的每個函數中的局部變量對於一個簡單的處理程序都是不可用的 - 因此,我想讓應用程序本身成爲堆中分配的單個對象,並通過全局指針刪除。 – bythescruff

2

如果你想從C++ C庫更可用,你也許可以在一個單獨的進程中運行它。然後確保(使用退出處理程序或其他方式)退出時,主應用程序會注意並拋出異常以展開自己的堆棧。也許在某些情況下,它可以以非致命的方式處理錯誤。

當然,將庫的使用轉移到另一個過程中可能並不容易,也不是特別有效。您需要做一些工作來封裝接口,並通過您選擇的IPC機制複製輸入和輸出。

作爲一個解決方案,使用您的主流程中的庫,但我認爲你描述的應該工作。風險在於,您無法識別和隔離需要清理的所有內容,或者將來有人會修改您的應用程序(或您使用的另一個組件),假設堆棧將正常展開。

可能修改庫源以調用運行時或編譯時可配置函數,而不是調用exit()。然後使用異常處理編譯庫並在C++中實現該函數以引發異常。麻煩的是,圖書館本身可能會泄漏錯誤資源,所以你必須使用這個例外來解開堆棧(也許會做一些錯誤報告)。即使錯誤可能是非致命的,就應用程序而言,不要抓住它並繼續。

1

如果呼叫exit而不是assertabort,有幾點需要得到再次控制:

  • 當調用exit,析構函數與靜態終身的對象(主要是:全局和對象與static聲明)仍然執行。這意味着您可以設置一個(少數)全局「資源管理器」對象並釋放它們的析構函數中的資源。
  • 正如您已經找到的,您可以使用atexit註冊掛鉤。這不僅限於一個。您可以註冊更多。

如果一切都失敗了,因爲你有庫的源代碼,你可以玩一些花樣宏用自己的功能,可以,例如,拋出一個異常,有效地更換調用exit

相關問題