2014-11-01 4 views
43

Od C Hadley najlepsze practices:Pakiety Must Must Czy należy rozładowywać biblioteki dynamiczne po wyładowaniu?

Podobnie jak C++, przy każdym użyciu kodu C w pakiecie, należy rozładować DLL, gdy opakowanie jest rozładowana:

.onUnload <- function (libpath) { 
    library.dynam.unload("mypackage", libpath) 
} 

Writing R Extensions z drugiej strony nawet o tym nie wspomina. Widzę, jak byłoby grzecznie wyładować biblioteki dll, ale robi to wydaje się powodować dziwne problemy dla mnie z pakietów, które są załadowane/rozładowane/przeładowane (patrz przykład dalej w dół). Ponadto, istnieją pewne wzmianki, które sugerują, że może nie być konieczne rozładowanie. Od ?library.dynam:

Należy pamiętać, że nawet, jeśli nie jest to możliwe, aby rozładować DLL, a następnie załaduj poprawioną wersję tego samego pliku jest zależny od systemu operacyjnego: patrz rozdział „wartość” na pomoc dla dyn.unload.

nie powinno to jednak wpływać na obiekty, które nie są modyfikowane. Wtedy nie jest to komentarz z Brian Ripley in R-devel:

Powiedziawszy to wszystko, moje doświadczenie jest to, że rozładunku DLL często nie pomaga, jeśli trzeba załadować go ponownie (i dlatego np tcltk nie rozładować jego DLL).

Czy można zostawić załadowane biblioteki C? Wolałabym nie musieć się zastanawiać, dlaczego dzieje się coś takiego jak poniżej (nie stało się to zanim zacząłem rozładowywać biblioteki).

R version 3.1.1 (2014-07-10) 
Platform: x86_64-apple-darwin13.1.0 (64-bit) 

> library(alike)  # install_github("brodieg/alike", ref="fdaa578e"), if you're curious 
> library(data.table) 
data.table 1.9.2 For help type: help("data.table") 
> detach("package:data.table", unload=T) 
> detach("package:alike", unload=T) 
> library(alike) 
> library(data.table) 
Error : .onLoad failed in loadNamespace() for 'data.table', details: 
    call: address(x) 
    error: object 'Caddress' not found 
In addition: Warning messages: 
1: In FUN(X[[9L]], ...) : 
    failed to assign RegisteredNativeSymbol for alike to alike since alike is already defined in the ‘data.table’ namespace 
2: In FUN(X[[9L]], ...) : 
    failed to assign RegisteredNativeSymbol for typeof to typeof since typeof is already defined in the ‘data.table’ namespace 
3: In FUN(X[[9L]], ...) : 
    failed to assign RegisteredNativeSymbol for type_alike to type_alike since type_alike is already defined in the ‘data.table’ namespace 
Error: package or namespace load failed for ‘data.table’ 

Ostrzeżenia dotyczą funkcji alike. alike nie użył do zwolnienia swoich bibliotek dynamicznych, a powyższe błędy nie wystąpiły. Po zaimplementowaniu rozładunku zaczęły się pojawiać błędy. Zauważ, że data.table 1.9.2 nie rozładował swoich bibliotek DLL, chociaż inne pakiety, które również nie zwalniają bibliotek DLL, nie spowodowały tego problemu. data.table 1.9.4 działa dobrze.

+0

Wiem, że to twoje pytanie, ale czy znalazłeś jakieś dodatkowe informacje na ten temat? – Dason

+0

@Dason, boi się, że nie. Natknąłem się również na [ten problem] (https://github.com/Rdatatable/data.table/issues/990) na 'data.table', który może być powiązany lub nie. Co więcej, nie miałem tego problemu od jakiegoś czasu, ale zbyt wiele się zmieniło, aby dokładnie wiedzieć, co to naprawiło. – BrodieG

+1

Dziwne.Mam nawyk automatycznego rozładowywania, ponieważ zostałem ugryziony przez debugowanie niewłaściwej wersji biblioteki DLL, którą zapomniałem zwolnić. Przepływ pracy: załaduj pakiet, znajdź błąd, napraw, załaduj ponownie pakiet. Ale biblioteka DLL nie została rozładowana. Ewps. Więc rada Hadley'a jest doskonała dla programistów. Ale nigdy nie widziałem takiego problemu jak twój na wolności. Interesujące rzeczy. – Jason

Odpowiedz

3

Normalnie rozładowanie biblioteki DLL byłoby dobrym pomysłem. Zasoby, które posiada, zostaną całkowicie uwolnione, a ponowne ładowanie nie będzie problemem.

W R występuje komplikacja środowiska R, ponieważ nawet jeśli biblioteka DLL zostanie wyładowana, może istnieć pewna wiedza pozostawiona w środowisku wykonawczym R. W takim przypadku wynikiem może być to, że ponownie załadowana biblioteka DLL nie ma takiego samego stanu wnioskowania co zmienne R, które mają na celu zrozumienie stanu biblioteki DLL, a zatem występują błędy.

Myślę, że byłoby możliwe, aby pakiet R (DLL i kod R) był bezpiecznie rozładowywany, ale łatwiej byłoby pozostawić załadowane biblioteki DLL, chyba że zauważysz szczególnie duże obciążenie zasobów.

+0

Tak. To bardzo zły pomysł, aby wyładować bibliotekę, jeśli nie masz pełnej kontroli nad wszystkimi wskaźnikami do tej biblioteki. Rozładowanie biblioteki jest dość nietypową operacją, a wiele programów nigdy nie wywołuje funkcji FreeLibrary(). Zasadniczo, alokacja zasobów i de-alokacja w pakiecie zewnętrznym, takim jak R, jest obowiązkiem samego pakietu, bez wyraźnego określenia w dokumentacji_, –

Powiązane problemy