簡體   English   中英

如果程序崩潰,如何釋放資源

[英]How to release resources if a program crashes

我有一個使用其他人服務的程序。 如果程序崩潰,關閉這些服務的最佳方法是什么? 在服務器端,我會定義一些檢查程序,監視客戶端是否定期無效。 但我們可以在客戶端做任何事情嗎? 如果正常的RAII在這種情況下仍能正常工作,我不確定。 我的代碼是用C和C ++編寫的。

如果您的應用程序遇到硬崩潰,那么不會,您的精心設計的清理代碼將無法運行,無論它是RAII范例的一部分還是您在main結束時調用的方法。 在導致應用程序終止的崩潰之后, 應用程序的清理代碼都不會運行。

當然,例外情況並非如此。 雖然這些可能最終導致應用程序終止,但它們仍然以受控方式觸發此終止。 通常,運行時庫將捕獲未處理的異常並觸發終止。 在此過程中,將執行基於RAII的清理代碼,除非它也拋出異常。 然后你又回到了毫不客氣地被撕掉的記憶中。

但即使您的應用程序的清理代碼無法運行, 操作系統仍會嘗試在您之后進行清理。 這解決了未釋放的內存,句柄和其他系統對象的問題。 一般來說,如果你崩潰了,你不必擔心發布這些東西。 您的應用程序的狀態不一致,因此嘗試執行一堆清理代碼只會導致不可預測且可能出現錯誤的行為,更不用說浪費大量時間了。 只是崩潰,讓系統處理你的爛攤子。 正如Raymond Chen所說

該建築正在拆除。 不要費心去掃地,清空垃圾桶,擦掉白板。 並且不要在建築物的出口處排隊,這樣每個人都可以將他們的進/出磁鐵移出。 你所做的只是讓拆遷隊等你完成這些毫無意義的清理工作。

做你必須做的事; 跳過其他一切。

這種方法的唯一問題是,正如您在此問題中所建議的那樣,當您管理不受操作系統控制的資源時,例如另一個系統上的遠程資源。 在這種情況下,你可以做的很少。 最好的方案是讓您的應用程序盡可能健壯,這樣它就不會崩潰,但即使這樣也不是一個完美的解決方案。 考慮當電源丟失時會發生什么, 例如因為用戶的貓從牆上拉下了電線。 因此,可能無法運行清理代碼,因此即使您的應用程序永遠不會崩潰,也可能存在超出您控制范圍的終止事件。 因此,在發生故障時,您的外部資源必須是健壯的。 超時是一種標准方法,也是比輪詢更好的解決方案。

根據具體的使用情況,另一種可能的解決方案是在應用程序初始化時運行一致性檢查和清理代碼。 這可能是您要為連續運行的服務所做的事情,並將在終止后立即重新啟動。 下次重新啟動時,它會檢查其數據和/或外部資源的一致性,發布和/或根據需要重新初始化它們,然后繼續正常運行。 顯然,這對於典型應用程序來說是一個糟糕的解決方案,因為無法保證用戶會及時重新啟動它。

正如其他答案所表明的那樣,希望在不受控制的崩潰之后進行清理(即,不會觸發C ++異常展開機制的故障)可能是一條無處可尋的路徑。 即使你覆蓋了某些情況,也會有其他情況失敗,而你正在構建一個嚴重的漏洞。

你提到崩潰的根源是你是“我們來自他人的服務”。 我認為這意味着您正在運行不受信任的代碼,這是崩潰的潛在來源。 在這種情況下,您可以考慮運行不受信任的代碼“進程外”並通過管道或共享內存或其他方式與主進程通信。 然后,您可以隔離此子進程的崩潰,並可以在主進程中進行受控清理。 一個單獨的進程實際上是你可以做的最輕量級的事情,它為你提供了避免調用代碼中的損壞所需的強大隔離。

如果分支每次調用進程的性能過高,則可以嘗試使子進程保持活動狀態以進行多次調用。

一種方法是讓您的程序有兩種模式:正常操作和監視。

當以通常的方式啟動時,它會:

  1. 充當背景監視器。
  2. 啟動它自己的子進程,傳遞一個內部參數(不會與傳遞給它的普通參數沖突,如果有的話)。
  3. 當子進程存在時,它將釋放服務器上保存的所有資源。

當使用內部參數啟動時,它會:

  1. 使用服務器的資源公開用戶界面並“正常行動”。

您可以查看atexit ,它可以為您提供在程序終止時釋放資源所需的功能。 不過,我不相信這是絕對正確的。

但話說回來,你應該專注於確保你的程序不崩潰; 如果您遇到“不可恢復”的錯誤,您仍應投入一些錯誤處理代碼。 如果錯誤是由Seg-Fault或其他類似的OS相關錯誤引起的,您可以啟用SEH異常(不確定這是否是特定於Windows的)以使您能夠使用正常的try-catch塊捕獲它們,或寫一些信號處理程序來攔截這些錯誤並處理它們。

暫無
暫無

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

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