6

Tylko dla czystej cholery, zdecydowałem się stworzyć Scheme binding to libpython, dzięki czemu można osadzać Python w programach Scheme. Mogę już zadzwonić do C API Pythona, ale tak naprawdę nie myślałem o zarządzaniu pamięcią.Czy są jakieś potencjometry odwołujące się do Pythona/wątki zbierania śmieci podczas pracy z kodem C?

Sposób działania funkcji FFI mzscheme polega na tym, że mogę wywołać funkcję, a jeśli funkcja zwróci wskaźnik do PyObject, mogę automatycznie zwiększyć wartość referencyjną. Następnie mogę zarejestrować finalizator, który zmniejszy licznik odwołań, gdy obiekt Scheme zbierze śmieci. Spojrzałem na documentation for reference counting i na pierwszy rzut oka nie widzę żadnych problemów (chociaż w niektórych przypadkach może to być nieoptymalne). Czy są jakieś zagubienia, których mi brakuje?

Mam także problemy z głowicami i ogonami cyclic garbage collector documentation. O jakich rzeczach muszę tutaj pamiętać? W szczególności, w jaki sposób mogę uczynić Pythona świadomym, że mam odnośnik do czegoś, więc nie zbiera go, kiedy wciąż go używam?

Odpowiedz

7

Twój link do http://docs.python.org/extending/extending.html#reference-counts jest właściwym miejscem. Sekcje Rozszerzenia i Osadzanie oraz Python/C API dokumentacji to te, które wyjaśnią, jak używać C API.

Zliczanie referencji jest jedną z denerwujących części korzystania z API C. Podstawowym problemem jest utrzymywanie wszystkiego prosto: w zależności od funkcji API, którą wywołujesz, możesz lub nie być właścicielem odniesienia do otrzymanego obiektu. Uważaj, aby zrozumieć, czy jesteś jego właścicielem (a zatem nie możesz zapomnieć o ZWOLNIENIA go lub dać mu czegoś, co go ukradnie) lub pożyczyć (i ZACHĘCIE go, aby go zachował i ewentualnie używał go podczas swojej funkcji). Najczęstsze błędy z tym związane to: 1) niepoprawne zapamiętywanie, czy masz referencję zwróconą przez daną funkcję i 2) uwierzenie, że możesz bezpiecznie wypożyczyć referencje przez dłuższy czas niż Ty.

Nie musisz robić nic specjalnego dla cyklicznego śmieciarza. Ma tylko załatać lukę w liczeniu referencji i nie wymaga bezpośredniego dostępu.

+0

Więc ... Python używa licznika odwołań * i * śmieciarki do cyklicznej struktury? To dość poważna wada. Rodzaj projektu. W każdym razie wygląda na to, że sprawi to, że Jason będzie o wiele bardziej "zabawny", jeśli jakiekolwiek wartości biorące udział w cyklu po stronie Pythona są narażone na schemat. –

+0

Dobre informacje. Tak długo, jak INCREF wszystko, kiedy to otrzymam i DECREF wszystko, gdy skończę, powinienem być OK? Czy są jakieś problemy, na które mogę się natknąć? –

+2

@Jason, tylko INCREF * wypożyczone * referencje. Niektóre funkcje zwracają * nowe * referencje, które są już WKRÓTCE. PODWYŻSZENIE ich spowodowałoby wyciek pamięci. –

3

Największe wrażenie, jakie znam z zliczaniem wyników, a API C to sprawa __del__. Kiedy masz pożyczone odniesienie do czegoś, myślisz, że możesz uciec bez INCREF'ing, ponieważ nie rezygnujesz z GIL podczas korzystania z tego odniesienia. Jeśli jednak usuniesz obiekt (na przykład, usuwając go z listy), możliwe, że wywołasz wywołanie __del__, które może usunąć odwołanie, które zapożyczasz spod nóg. Bardzo trudne.

Jeśli INCREF (a następnie DECREF, oczywiście) wszystkie wypożyczone odniesienia, jak tylko je otrzymasz, nie powinno być problemu.

Powiązane problemy