Autor Wątek: Singleton - co z tym jest nie tak  (Przeczytany 3389 razy)

Offline Veldrin

  • Użytkownik

# Marzec 13, 2012, 23:11:01
agent_J: dokładnie o to mi chodzi. Dynamiczne zarządzanie zasobami - oczywista sprawa. Wybieramy język bez GC - trzeba pamiętać. W przeciwnym wypadku - od tego jest OS. Dlatego uważam, że dyskusja jest mało praktyczna w kontekście sprzątania "na koniec".

Poza faktem, że czasem jest to uznawane za "dobrą praktykę".

polygon7: przykład? Z ciekawości pytam, bo pisałem kod na różne systemy, nie spotkałem się z taką kwestią. Taki wiesz, wykorzystywany i rozwijany. No i na który programowanie obiektowe ma sens/wykorzystanie ;) jak wskazał agent_J.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline bies

  • Użytkownik

# Marzec 14, 2012, 00:34:47
Jeśli to jest biblioteka, która może być wielokrotnie inicjalizowana/niszczona w trakcie działania aplikacji, to sprzątanie musi być jak najbardziej. W przeciwnym przypadku można to kompletnie olać.  Wszystkie zasoby będą zwolnione przez jądro systemu przy zamykaniu aplikacji. Jądro ma w odbycie rzeczy typu malloc w userspace - dla jądra istnieje tylko VirtualAlloc/Free/mmap/itp., za pomocą których zasoby utworzone niszczone są przy zamykaniu procesu. Sockety, pliki (uchwyty) - niszczone przez jądro.
Nie wszystkie. Np. jeśli nie wywołasz SDL_Quit() to X11 (nie wiem jak Windows) nie przywróci gammy pulpitu mimo, że aplikacja zakończy się poprawnie.

// edit
Z resztą gniazdka też nie zamkną się tak po prostu tylko wpadną w stan TIME_WAIT. Jeśli zbindujesz się na porcie a następnie zakończysz proces i uruchomisz go ponownie bez zamknięcia kolejny bind() się nie powiedzie.

// edit^2
Veldrin: OS 4690, jakaś wczesna wersja (na nowszych nie próbowałem). To taki IBM-a OS do POS-ów i jak najbardziej jest wykorzystywany. No więc jakieś paręnaście lat temu napisałem aplikację która wyczerpała wszystkie gniazda (zapomniałem o closesocket()).
« Ostatnia zmiana: Marzec 14, 2012, 00:45:31 wysłana przez bies »

Offline Kos

  • Użytkownik
    • kos.gd

# Marzec 14, 2012, 10:46:36
A co to spowoduje ? Usuwanie obiektu o adresie 0 chyba nie spowoduje błędu ?

Delete można bezpiecznie odpalić na zerowym wskaźniku, jasne. Pytanie: Kiedy ostatnio w swoim kodzie zerowałeś w destruktorze wskaźnik zaraz po delete? :-)

A mówiłem o tym, że destruktora nie woła się dwa razy, bo może w nim być coś "ciekawszego" niż alokacja pamięci-  odwołania do systemowych zasobów, jakaś logika aplikacji nawet, no i kaskadują się destruktory obiektów pochodnych.

Dlatego jak wołasz destruktor samemu, to prosisz się o kłopoty, bo ktoś go na tym samym obiekcie zawoła po raz drugi (dla obiektów automatycznych wiadomo kiedy, a alokowane dynamicznie ktoś kiedyś skasuje przez delete).

Jedyna w sumie sytuacja, gdy wołanie destruktora ręcznie jest przydatne, to w parze z placement new.

Offline tomaszwir

  • Użytkownik

# Marzec 15, 2012, 16:35:49
Aha... A dziwny destruktor który wywołuje się nie wiadomo jak i nie wiadomo przez kogo to oczywiście jest zupełnie intuicyjne i poprawne rozwiązanie, które nie wprowadza zamieszania w kodzie?
....
....
Cały pomysł z wywoływaniem delete w destruktorze jest tu wysoce kuriozalny, bo jedynym obiektem który może zostać zniszczony - a więc wywołać ów destruktor - jest ten właśnie jedyny obiekt który chcemy w ten sposób zniszczyć. Widać tu pewien cyrkularny problem, czyż nie?
Zaraz zaraz, czyli ten destruktor się nie wywoła ? Musiał by być wywołany przez delete które jest w destruktorze ? Ciężko mi to sobie poukładać....

Okej, a teraz trochę poważniej. Jeśli NAPRAWDĘ nie potrafisz określić czasu życia tego swojego singletona (hint: powinieneś być w stanie to zrobić)
W przypadku rozwiązanie bez wskaźnika, to czas życia obiektu to od pierwszego użycia do zamknięcia aplikacji ?

Albo się teraz mylę albo zrozumiałem, cała przewaga rozwiązania ze wskaźnikiem polega na tym że można bezproblemowo kontrolować czas życia obiektu, i usunąć go kiedy nie jest już potrzebny, zgadza się ?

Offline ismu

  • Użytkownik

# Marzec 15, 2012, 22:41:15
Co do pierwszego. Właśnie mój przykład(błędny nielogiczny i w ogóle) miał posłużyć, żebyś zrozumiał, że coś ten destruktor musi wywołać a nie że jak wrzucimy sobie delete do destruktora to będzie wszystko ok. Dlatego w singletonie powinna być metoda DeleteInstance() z delete, bo wtedy będziesz miał możliwość skasowania obiektu