本文說明例外狀況發生時釋放物件的需求和方法。 主題包括:
架構或應用程式所擲回的例外狀況會中斷一般程式流程。 因此,請務必密切追蹤物件,以便在擲回例外狀況時能正確地處理它們。
有兩個主要方法可以執行這項作。
使用
try和catch關鍵詞在本機處理例外狀況,然後使用一個語句終結所有物件。在將例外狀況拋出區塊外部以進一步處理之前,先銷毀
catch區塊中的任何物件。
以下說明這兩種方法是下列有問題範例的解決方案:
void SomeFunc() // Problematic code
{
CPerson* myPerson = new CPerson;
// Do something that might throw an exception.
myPerson->SomeFunc();
// Now destroy the object before exiting.
// If SomeFunc above throws an exception this code will
// not be reached and myPerson will not be deleted.
delete myPerson;
}
如上所述,如果 myPerson 擲出例外狀況,SomeFunc 將不會被刪除。 執行會直接跳至下一個外部例外狀況處理程式,略過一般函式結束和刪除物件的程序代碼。 當例外狀況離開函式時,物件的指標超出範圍,只要程式正在執行,物件所佔用的記憶體就永遠不會復原。 這是記憶體流失;它會使用記憶體診斷來偵測到。
當地處理例外狀況
try/catch 範例提供防禦性程序設計方法,可避免記憶體流失,並確保發生例外狀況時會終結您的物件。 例如,本文稍早所示的範例可能會重寫如下:
void SomeFunc()
{
CPerson* myPerson = new CPerson;
try
{
// Do something that might throw an exception.
myPerson->SomeFunc();
}
catch (CException* e)
{
// Handle the exception locally
e->Delete();
}
// Now destroy the object before exiting.
delete myPerson;
}
這個新範例會設定例外狀況處理程式來攔截例外狀況,並在本機處理例外狀況。 然後它會正常結束函式,並終結 物件。 此範例的重要部分是使用 try/catch 區塊建立捕獲例外狀況的上下文。 如果沒有本機例外處理框架,函式將無法知道已丟擲例外狀況,也因此無法有機會正常結束和銷毀物件。
銷毀物件後拋出例外狀況
另一個處理例外狀況的方法,是將它們傳遞至下一個外部例外狀況處理內容。 在您的 catch 區塊中,您可以對本機配置的對象進行一些清理,然後拋出例外以供進一步處理。
拋出函式可能需要或可能不需要釋放堆疊記憶體物件。 如果函式在一般情況下總是會在傳回之前釋放堆疊物件,那麼函式也應該在擲回例外狀況之前釋放堆疊物件。 另一方面,如果函式在一般案例中傳回之前通常不會解除分配物件,則您必須根據大小寫來決定是否應該解除分配堆積物件。
下列範例示範如何清除本機配置的物件:
void SomeFunc()
{
CPerson* myPerson = new CPerson;
try
{
// Do something that might throw an exception.
myPerson->SomeFunc();
}
catch (CException* e)
{
e->ReportError();
// Destroy the object before passing exception on.
delete myPerson;
// Throw the exception to the next handler.
throw;
}
// On normal exits, destroy the object.
delete myPerson;
}
例外狀況機制會自動釋放框架物件;框架物件的解構子也會被呼叫。
如果您呼叫可以擲回例外狀況的函式,您可以使用 try/catch 區塊來確保攔截例外狀況,並有機會終結您所建立的任何物件。 特別是請注意,許多 MFC 函式可能會引發例外狀況。
如需詳細資訊,請參閱 例外狀況:攔截和刪除例外狀況。