例外狀況:釋放例外狀況中的物件
本文說明當例外狀況發生時,為何需要釋放物件以及其方法。 主題包括:
在本機處理例外狀況
在終結物件之後擲回例外狀況
架構或您的應用程式執回例外狀況會中斷一般程式流程。 因此,保留物件存取追蹤是非常重要的,這讓您能在擲回例外狀況時正確處理它們。
執行這項作業的方法有兩種。
使用 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;
}
如前述,若 SomeFunc 擲回例外狀況,則 myPerson 不會被刪除。 執行會直接跳至下一個外部例外處理常式,略過正常功能結束和刪除物件的程式碼。 當例外狀況離開函式時,物件的指標會超出範圍,而只要程式執行,物件所佔用的記憶體不會復原。 這是記憶體遺漏 (Memory Leak);若使用記憶體診斷將會偵測到它。
在本機處理例外狀況
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 函式可以擲回例外狀況。
如需詳細資訊,請參閱 例外狀況:攔截和刪除例外狀況。