Edytuj: komentarze poniżej zaakceptowanej odpowiedzi wskazują, że może to być problem z dynamicznym programem ładującym systemu Android.Statyczny * szablon * element członkowski w bibliotece dynamicznej
Mam nagłówek dla klasy szablonu ze statycznym członkiem. W środowisku wykonawczym adres statycznego elementu jest używany w bibliotece iw kodzie klienta. Szablon jest niejawnie utworzony zarówno w bibliotece, jak iw kodzie klienta. Działa dobrze na systemach Linux i OSX, symbol jest duplikowany, ale oznaczony jako "unikalny", jak pokazano za pomocą nm (patrz poniżej). Jednak gdy kompiluję dla ARM (Android), symbol jest oznaczony jako słaby zarówno w DSO, jak iw pliku wykonywalnym. Program ładujący nie unifikuje się, a symbol jest skutecznie duplikowany w czasie wykonywania!
czytam te: two instances of a static member, how could that be? Static template data members storage a zwłaszcza tę odpowiedź: https://stackoverflow.com/a/2505528/2077394 oraz: http://gcc.gnu.org/wiki/Visibility
ale nadal jestem trochę zdziwiony. Rozumiem, że atrybuty widoczności pomagają zoptymalizować, ale pomyślałem, że powinien działać domyślnie. Wiem, że standard C++ nie dba o bibliotekę współdzieloną, ale czy oznacza to, że używanie bibliotek współdzielonych łamie standard? (lub przynajmniej ta implementacja nie jest zgodna ze standardem C++?) Bonus: jak mogę to naprawić? (A nie przy użyciu szablonu nie jest dopuszczalne odpowiedź :))
Header:
template<class T>
struct TemplatedClassWithStatic {
static int value;
};
template<class T>
int TemplatedClassWithStatic<T>::value = 0;
shared.cpp:
#include "TemplateWithStatic.hpp"
int *addressFromShared() {
return &TemplatedClassWithStatic<int>::value;
}
main.cpp:
#include "TemplateWithStatic.hpp"
#include <cstdio>
int *addressFromShared();
int main() {
printf("%p %p\n", addressFromShared(), &TemplatedClassWithStatic<int>::value);
}
i budynku , patrząc na definicje symboli:
wytwarzania .so:
g++-4.8 -shared src/shared.cpp -o libshared.so -I include/ -fPIC
kompilowania i łączący główne:
g++-4.8 src/main.cpp -I include/ -lshared -L.
Symbole są oznaczone jako "Unikalny":
nm -C -A *.so a.out | grep 'TemplatedClassWithStatic<int>::value'
libshared.so:0000000000200a70 u TemplatedClassWithStatic<int>::value
a.out:00000000006012b0 u TemplatedClassWithStatic<int>::value
wytwarzania .so
~/project/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++ -o libshared.so src/shared.cpp -I include/ --sysroot=/Users/amini/project/android-ndk-r9/platforms/android-14/arch-arm/ -shared
kompilowanie i łączenie główne
~/project/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++ src/main.cpp libshared.so -I include/ --sysroot=${HOME}/project/android-ndk-r9/platforms/android-14/arch-arm/ -I ~/project/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/include -I ~/project/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I ~/project/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/include/backward -I ~/project/android-ndk-r9/platforms/android-14/arch-arm/usr/include ~/project/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/libgnustl_static.a -lgcc
symbole są słabe!
nm -C -A *.so a.out | grep 'TemplatedClassWithStatic<int>::value'
libshared.so:00002004 V TemplatedClassWithStatic<int>::value
a.out:00068000 V TemplatedClassWithStatic<int>::value
Edit, uwaga dla kontekstu: Grałem z OOLua, biblioteka pomaga wiązania C++ do Lua i moich unittests dopuściły kiedy zacząłem kierować Android. Nie "posiadam" kodu i wolę go raczej głęboko modyfikować.
Edit, aby go uruchomić na Androidzie:
adb push libshared.so data/local/tmp/
adb push a.out data/local/tmp/
adb shell "cd data/local/tmp/ ; LD_LIBRARY_PATH=./ ./a.out"
0xb6fd7004 0xb004
Dzięki. Czy powinienem stwierdzić, że toolchain Androida nie obsługuje w pełni standardu C++, o ile zaczniesz używać bibliotek współdzielonych? – Joky
"Toolchain Android nie obsługuje w pełni standardu C++, o ile zaczniesz korzystać z bibliotek współdzielonych" - moje własne eksperymenty ze słabymi symbolami (w systemie Linux) sugerują, że faktycznie działają w przypadku danych statycznych w bibliotekach współdzielonych. Oznacza to, że linker wymusi użycie tylko jednego ze słabych symboli, inne wystąpienia zostaną zignorowane. Czy próbowałeś uruchomić swój program? –
Tak, adres wydrukowany jest inny (tylko na Androidzie) – Joky