C++ wskaźniki a wyjątki

0

Cześć,
tak się zastanawiam. Pisząc aplikację bez użycia jakichś inteligentnych wskaźników, tylko zwykłych jeżeli stworzymy jakiś obiekt.

Cos* obiekt = new Cos();
//(...) jakieś operacje
delete obiekt;

to jeśli w trakcie tych jakichś operacji poleci jakiś wyjątek, to mamy wyciek pamięci? Bo nie zwolniliśmy pamięci sami.

Rozwiązanie jakie mi przyszło do głowy to po prostu try-catch ale z drugiej strony jeśli tworzymy tych obiektów np 100 różnych,
to potem w catchu sprawdzać tą setkę, który należy zwolnić to chyba też nie jest szczęśliwy pomysł.

To jest taki mankament, który jeszcze mnie wstrzymuje przy próbie zrozumienia pracy ze wskaźnikami.
Mógłby mi ktoś wytłumaczyć jak to działa, jak się ustrzec przed powyższym? Tzn jak to obsłużyć żeby nie mieć leaka.

0

Poczytaj o RAII.

0

I dlatego właśnie wymyślono smart pointery.

0

po co nie używać smart pointerów? (unique_ptr, w tym przypadku)

0

Oczywiście że nie musisz używać inteligentnych wskaźników.

Możesz robić to samo przez try/catch, tylko to jest więcej roboty. No ale jak wolisz.

Żeby użyć unique_ptr trzeba mieć C++11.
Albo wymieniać z auto_ptr w zależności od kompilatora.

0

Co do inteligentnych wskaźników to nie zaleca się używania auto_ptr - jest to proszenie się o kłopoty. Jeśli ma się C++11 to trzeba używać unique_ptr, jeśli mamy boost to można shared_ptr, jeśli jednak tworzymy obiekt lokalnie to wtedy scoped_ptr.
http://www.boost.org/doc/libs/1_53_0/libs/smart_ptr/smart_ptr.htm

Jeśli chodzi o wycieki w jak to nazwałeś jakiś operacjach to te właśnie operacje są odpowiednio wywoływane w tych właśnie konkretnych jakiś metodach. Dzięki temu łapane są wyjątki w danej metodzie. Dzięki temu nie gubimy obiektu. Inną sprawą jest natomiast moment tworzenia obiektu. Jeśli w konstruktorze inicjalizujemy jakieś zasoby i wtedy coś pójdzie nie tak, wtedy mamy problem i wtedy jest duże ryzyko wycieków pamięci, ponieważ jeśli obiekt nie dokończy konstruktora, wtedy nie wywoła się destruktor a co za tym idzie wszystko to co było do momentu wywrotki zaalokowane to będzie wisieć. Dlatego zaleca się w konstruktorach robienie minimum. Wszelkie prace na zasobach warto wydzielić do oddzielnych metod, które są wywoływane po zaalokowaniu obiektu. Jeśli wtedy coś pójdzie nie tak i obiekt zostanie zniszczony to mamy pewność, że destruktor zostanie wywołany.

Inna sprawą jest zgubienie wskaźnika - wtedy właśnie pomocne są inteligentne wskaźniki.

0
CppBeginner napisał(a):

Cześć,
tak się zastanawiam. Pisząc aplikację bez użycia jakichś inteligentnych wskaźników, tylko zwykłych jeżeli stworzymy jakiś obiekt.

Cos* obiekt = new Cos();
//(...) jakieś operacje
delete obiekt;

to jeśli w trakcie tych jakichś operacji poleci jakiś wyjątek, to mamy wyciek pamięci? Bo nie zwolniliśmy pamięci sami.

Rozwiązanie jakie mi przyszło do głowy to po prostu try-catch ale z drugiej strony jeśli tworzymy tych obiektów np 100 różnych,
to potem w catchu sprawdzać tą setkę, który należy zwolnić to chyba też nie jest szczęśliwy pomysł.

To jest taki mankament, który jeszcze mnie wstrzymuje przy próbie zrozumienia pracy ze wskaźnikami.
Mógłby mi ktoś wytłumaczyć jak to działa, jak się ustrzec przed powyższym? Tzn jak to obsłużyć żeby nie mieć leaka.

Jeśli masz 100 obiektów to prawdopodobnie źle zaprojektowałeś algorytm i używasz jednej dużej
funkcji, zamiast 10ciu małych. Podziel na małe procedury, stanie się dużo łatwiej. Jeśli specyfika
Twojego programu wymaga skomplikowanej analizy tego co zostało niepotrzebnie zaallokowane,
to zaprojektuj specjalną strukturę do tego celu, np. listę. Wtedy w sekcji catch przeglądasz
listę i zwalniasz w jednej prostej pętli. Możesz też zwalniać po sekcji catch.

Allocated all;
try {
Obj1 obj1;
Obj2 obj2;
//itd
all.append( obj1 = new Obj1() );
//jakieś operacje;
all.append( obj2 = new Obj2() );
//itd
} catch(...) {
// obsługa samego błędu
}
while( next = all() )
delete next;
}

Generalnie: jeśli jakakolwiek operacja jest skomplikowana w implementacji, to trzeba przygotować
zestaw struktur/procedur do jej obsługi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1