Mam aplikację C++ na wielu platformach, która jest podzielona na kilka bibliotek współdzielonych i ładuje dodatkową funkcjonalność z bibliotek współdzielonych wtyczek. Biblioteki wtyczek mają być samodzielne i funkcjonować samodzielnie, bez znajomości lub zależności od aplikacji wywołującej.Segfault w bibliotece wtyczek C++ z podwójnymi symbolami
Jedna z wtyczek zawiera skopiowany kod z głównej aplikacji, więc zawiera nazwy symboli, które są duplikatem tych w silniku. (Tak, wiem, że na ogół nie jest to możliwe, ale w chwili pisania wtyczki silnik był monolitycznym plikiem binarnym i nie mógł udostępniać bibliotek.) W systemie Windows wszystko działa poprawnie. W Linuksie dostaliśmy segfaults. Patrząc na ślad stosu błędu, wystąpił on w wtyczce podczas wywoływania funkcji w zduplikowanej nazwie klasy. Wygląda na to, że jest wynikiem silnika i wtyczki posiadającej nieco inne wersje wspólnego kodu (niektóre funkcje klasy zostały skomentowane w wtyczce). Wyglądało to tak, jakby wtyczka pobierała swoje środowisko uruchomieniowe symboli do silnika zamiast własnego. "Naprawiliśmy" problem, zmieniając parametry dlopen
na dlopen(pFilepath, RTLD_LAZY | RTLD_LOCAL)
.
Ale kiedy przepisaliśmy silnik, aby został podzielony na współdzielone biblioteki (w celu ewentualnego ponownego użycia w wtyczkach), otrzymamy ponownie błąd segfault. I patrząc na ślad stosu, wychodzi z silnika -> plugin -> engine.
Czy istnieje sposób, aby dla łącznika środowiska wykonawczego nie mapować symboli wtyczki do silnika (szczególnie jeśli są zdefiniowane w wtyczce)?
Dzięki! Matt
Edited 2009-12-3
raz pierwszy próbował owinąć kod wtyczki w jego własnej przestrzeni nazw. To nie zadziałało, ponieważ jest statycznie połączone z biblioteką, która jest również połączona z silnikiem. Wersje biblioteki statycznej są różne, więc segfault!
Następnie zmieniłem kompilację silnika i jego bibliotek, aby były statycznie połączone. A kiedy go uruchomię, nie mam już problemu. Wygląda więc na to, że był on eksportowany, a następnie dynamicznie przenoszony do wtyczki podczas jej otwierania. Ale gdy cały kod silnika znajduje się w jednym pliku wykonywalnym, nie eksportuje swoich symboli (więc nie próbuje przenosić symboli wtyczki do silnika).
Nadal mam problem, ponieważ istnieje równoległa wersja programu (z wykorzystaniem Open-MPI), która nadal otrzymuje błąd segfault. Wygląda na to, że wciąż eksportuje symbole silnika i przenosi wtyczki. To może mieć związek z tym, jak Open-MPI wykonuje aplikację.
Czy istnieją flagi linkerów, które mogą być używane w bibliotece współdzielonej wtyczek, które powiedziałyby jej, aby nie zmieniała dynamicznie symboli w środowisku wykonawczym? A może ukryć symbole, żeby się nie przenosiły? Próbowałem już -s
("Pomiń wszystkie informacje o symbolu"), ale to najwyraźniej nie zmieniło symboli dynamicznych (zaznaczone przy użyciu nm -D <plugin>
).
Czy są to symbole globalne lub nazwy funkcji? Czy możesz wprowadzić drobne zmiany w kodzie? –
Są to zajęcia i ich funkcje członkowskie. W bazie kodu silnika znajduje się 36 plików, więc nie chcę modyfikować nazw ani plików klas. Chociaż ostatecznym celem jest przepisanie wtyczki, ze względu na ograniczenia czasowe i sprawdzanie poprawności kodu, nie chcę, jeśli nie muszę. – CuppM
@CuppM, więc na przykład masz klasę "Foo" z członkiem "bar" zdefiniowanym w 2 miejscach? A "Foo" ma w obu przypadkach taką samą przestrzeń nazw? Jeśli tak, to nigdy nie będzie działać prawidłowo. Przenieś jeden z "Foo" do jego własnej przestrzeni nazw i życie będzie łatwiejsze. – Glen