Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule wyjaśniono potrzebę i metodę zwalniania obiektów w przypadku wystąpienia wyjątku. Tematy obejmują:
Wyjątki zgłaszane przez platformę lub przez aplikację przerywają normalny przepływ programu. W związku z tym bardzo ważne jest zachowanie ścisłego śledzenia obiektów, dzięki czemu można je prawidłowo usunąć w przypadku zgłoszenia wyjątku.
Istnieją dwie podstawowe metody, aby to zrobić.
Lokalnie obsługuj wyjątki za pomocą słów kluczowych
tryicatch, a następnie zniszcz wszystkie obiekty za pomocą jednej instrukcji.Zniszcz dowolny obiekt w bloku
catchprzed zgłoszeniem wyjątku poza blokiem w celu dalszej obsługi.
Te dwa podejścia przedstawiono poniżej jako rozwiązania następującego problematycznego przykładu:
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;
}
Zgodnie z powyższym, myPerson nie zostanie usunięty, jeśli wyjątek zostanie zgłoszony przez SomeFunc. Wykonanie przechodzi bezpośrednio do następnego zewnętrznego obsługiwacza wyjątków, pomijając normalne zakończenie funkcji i kod, który usuwa obiekt. Wskaźnik do obiektu wykracza poza zakres, gdy wyjątek opuszcza funkcję, a pamięć zajmowana przez obiekt nigdy nie zostanie odzyskana, o ile program jest uruchomiony. Jest to przeciek pamięci; zostanie wykryta przy użyciu diagnostyki pamięci.
Obsługa wyjątku lokalnie
Model try/catch zapewnia defensywną metodę programowania umożliwiającą uniknięcie przecieków pamięci i zapewnienie, że obiekty są niszczone w przypadku wystąpienia wyjątków. Na przykład przykład przedstawiony wcześniej w tym artykule może zostać przepisany w następujący sposób:
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;
}
W tym nowym przykładzie skonfigurowana jest procedura obsługi wyjątków w celu przechwycenia wyjątku i obsługi go lokalnie. Następnie wychodzi z funkcji w normalny sposób i niszczy obiekt. Ważnym aspektem tego przykładu jest to, że kontekst do przechwycenia wyjątku jest ustanawiany przy użyciu bloków try/catch . Bez lokalnej ramki wyjątków funkcja nigdy nie dowiedziałaby się, że zgłoszono wyjątek, i nie miałaby szansy na normalne zakończenie oraz zniszczenie obiektu.
Zgłaszanie wyjątków po zniszczeniu obiektów
Innym sposobem obsługi wyjątków jest przekazanie ich do następnego zewnętrznego kontekstu obsługi wyjątków. W bloku catch możesz wykonać czyszczenie obiektów przydzielonych lokalnie, a następnie przekazać wyjątek do dalszego przetwarzania.
Funkcja throwing może lub nie musi cofnąć przydziału obiektów stert. Jeśli funkcja zawsze cofa przydział obiektu sterta przed zwróceniem w normalnym przypadku, funkcja powinna również cofnąć przydział obiektu sterta przed zgłoszeniem wyjątku. Z drugiej strony, jeśli funkcja nie zwalnia zwykle obiektu przed jego zwróceniem w typowym przypadku, musisz decydować indywidualnie, czy obiekt sterty powinien zostać zwolniony.
W poniższym przykładzie pokazano, jak można wyczyścić obiekty przydzielone lokalnie:
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;
}
Mechanizm wyjątków automatycznie dealokuje obiekty ramki; destruktor obiektu ramki zostaje również wywołany.
Jeśli wywołasz funkcje, które mogą zgłaszać wyjątki, możesz użyć bloków try/catch , aby upewnić się, że przechwytujesz wyjątki i masz szansę zniszczyć wszystkie utworzone obiekty. W szczególności należy pamiętać, że wiele funkcji MFC może zgłaszać wyjątki.
Więcej informacji znajdziesz w Wyjątki: przechwytywanie i usuwanie wyjątków.