异常:释放异常中的对象
,发生异常时,本文说明需求和释放对象的方法。 主题包括:
处理异常局部
引发的异常在销毁对象之后
您的应用程序引发的由框架或异常中断常规程序流。 因此,保留对象接近的跟踪非常重要,以便可以正确处理它们,如果将引发异常。
执行此操作有两种主要方法。
使用 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 不会被删除。 执行直接跳转到下外部异常处理程序,跳过功能正常退出和删除对象的代码。 指向对象的指针超出范围,当异常出函数时,因此,对象占用的内存不会恢复,只要程序运行。 这是内存泄漏;通过使用内存诊断,则将检测。
处理异常局部
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 函数可能会引发异常。
有关更多信息,请参见 异常:捕获和删除异常。