2011-01-12 13 views
5

Chociaż myślę, że rozumiem istotę problemu (tj. Dobra GC utworów obiektów, a nie zakres), nie wiem wystarczająco dużo na temat, aby przekonać innych.Dlaczego RAII i wyrzucanie śmieci wzajemnie się wykluczają?

Czy możesz podać mi wyjaśnienie, dlaczego nie ma języków gromadzących śmieci z deterministycznymi destruktorami?

+0

-1 Pytanie jest błędne. Są to śmieci zbierane języki z deterministycznymi destruktorami, np. 'IDisposable' na .NET zapewnia deterministyczne zniszczenie dla C#, VB.NET i F #. –

Odpowiedz

3

NIE wzajemnie się wykluczają. Zapraszam do korzystania z C++ z libgc (Boehm-Reiser-Detlefs collector). Nadal możesz korzystać z RAII, inteligentnych wskaźników i ręcznego usuwania, ale przy uruchomionym GC możesz po prostu "zapomnieć" o usunięciu niektórych obiektów.

@ Odpowiedź Andy'ego dotycząca zbyt późnego dysponowania zasobami mija się z istotną kwestią: to nie opóźnienie w udostępnianiu zasobów ma kluczowe znaczenie semantyczne, ale raczej kolejność wydania.

Powodem, dla którego GC ma tendencję do tego, by nie zamówić dobrze wydania, jest to, że wymagałoby to sortowania topologicznego na potrzeby zamawiania (zależności) i jest to kosztowny algorytm.

Niemniej jednak, Ocaml GC ma interesujący obiekt, w którym można dołączyć finalizator do obiektu. Jeśli obiekt stanie się nieosiągalny, uruchomi się finalizator, jednak obiekt nie zostanie usunięty (ponieważ finalizator może uczynić go ponownie osiągalnym: w takim przypadku można nawet dołączyć inny finalizator). Te finalizatory mogą zapewnić pewną kontrolę nad zamówieniami.

+0

Kolejność wydania może być ważna. Nieocenione może być również niezdefiniowane opóźnienie w wydaniu i możliwe całkowite niepowodzenie zwolnienia. To nie jest ani - ani, ani jedno, ani drugie. –

+0

Nieokreślone opóźnienie zwolnienia może rzeczywiście być ważne, co obejmuje zwolnienie pamięci! Wydajność ma znaczenie. Ale nie jest to istotne semantycznie. Całkowite niepowodzenie zwolnienia ma jednak znaczenie, ale nie może się zdarzyć, jeśli GC zostanie uruchomiony w punkcie zakończenia. W przypadku niektórych zasobów, takich jak uchwyty plików w systemie Unix, zwykle nie uruchamia się GC po zakończeniu, ponieważ system i tak zwolni zasoby. Ogólną radą przy użyciu GC jest NIE używanie RAII do krytycznych zasobów, zwolnienie w ramach kontroli programu. Jednak nie jest jasne, co to oznacza z leniwą oceną np. W Haskell. – Yttrill

0

Od Wikipedia, po stwierdzeniu, że śledzenie śmieciarze są najczęstszym typem:

Kalka zbieranie śmieci nie jest deterministyczny. Obiekt, który staje się kwalifikuje się do zbierania śmieci, będzie prawdopodobnie ostatecznie oczyszczony, ale nie ma gwarancji, kiedy (a nawet jeśli) się stanie.

W związku z tym korzystanie z RAII może doprowadzić do zbyt późnego usunięcia zasobów.

W rezultacie na przykład Java ma wytyczną do "unikania finalizatorów" (pozycja 6 w "Efektywna Java" Josua Blocha). "W finalizatorze nigdy nie powinno się robić nic krytycznego".

+0

FWIW Strona Wikipedii na temat usuwania śmieci jest w większości błędna, łącznie z tą sekcją. –

+0

@JonHarrop - Wszelkie konkretne uwagi krytyczne dotyczące tej odpowiedzi są mile widziane. –

+0

Jest jasne, że działanie prostego algorytmu GC jest całkowicie deterministyczne w pojedynczej aplikacji z gwintem. Może być trudne, ale nie musi być trudne do przewidzenia, ale mój system ma co najmniej jedno wyraźne wywołanie metody collect(), które uruchamia GC i będzie uruchamiać finalizatory. Determinizm gubi się tylko w aplikacjach wielowątkowych, które w jakiś sposób mogą mieć ograniczony lub nieograniczony niedeterminizm (w zależności od systemu i aplikacji), więc nie jest jasne, czy nawet w takim przypadku GC sprawia, że ​​rzeczy są gorsze, niż są już. – Yttrill

0

Śmieciarz nie może działać cały czas (liczenie się zbliża, ale generalnie nie liczy się jako odśmiecanie), więc nawet nie próbuje. Jest to niepraktyczne. Dlatego istnieje nieuniknione opóźnienie pomiędzy niedostępnością obiektu (np. Dlatego, że jedyne odniesienie wykracza poza zakres) i gromadzeniem go przez GC, prawdopodobnie wypuszczając finalizatora. Opóźnienie to nie jest deterministyczne ... chyba że (a następnie deterministyczne zniszczenie w ścisłym tego słowa znaczeniu jest możliwe, choć wciąż niepraktyczne) wymusza GC na deterministyczny harmonogram - ale to zbliża się do "GC działającego cały czas" , co wciąż jest niesamowicie niepraktyczne.

Zatem GC i deterministyczne porządki wzajemnie się wykluczają, ponieważ GC dokonuje wszystkich porządków i nie może sobie pozwolić na to, że są deterministyczne, ale musi polegać na maksymalizacji wydajności.

Powiązane problemy