Chỉnh sửa: các nhận xét bên dưới câu trả lời được chấp nhận cho thấy rằng đó có thể là sự cố với trình tải động của Android.Thành phần lớp * * tĩnh trên thư viện động
Tôi có một tiêu đề cho một lớp mẫu với một thành viên tĩnh. Khi chạy, địa chỉ của thành viên tĩnh được sử dụng trong thư viện và trong mã máy khách. Mẫu được khởi tạo ngầm cả trong thư viện và trong mã máy khách. Nó hoạt động tốt trên Linux và OSX, biểu tượng được nhân bản nhưng được đánh dấu là "không độc nhất" như được hiển thị bởi nm (xem bên dưới). Tuy nhiên khi tôi biên dịch cho ARM (Android), biểu tượng được đánh dấu yếu trong cả DSO và tệp thực thi. Trình tải không thống nhất và biểu tượng được sao chép một cách hiệu quả vào thời gian chạy!
tôi đọc những: two instances of a static member, how could that be? Static template data members storage và đặc biệt là câu trả lời này: https://stackoverflow.com/a/2505528/2077394 và: http://gcc.gnu.org/wiki/Visibility
nhưng tôi vẫn còn một chút bối rối. Tôi hiểu rằng các thuộc tính cho khả năng hiển thị giúp tối ưu hóa, nhưng tôi nghĩ nó sẽ hoạt động theo mặc định. Tôi biết tiêu chuẩn C++ không quan tâm đến thư viện được chia sẻ, nhưng điều đó có nghĩa là việc sử dụng các thư viện chia sẻ phá vỡ tiêu chuẩn? (hoặc ít nhất việc thực hiện này không phải là tiêu chuẩn C++ phù hợp?) Tiền thưởng: làm thế nào tôi có thể sửa nó? (Và không sử dụng mẫu không phải là một câu trả lời có thể chấp nhận :))
Tiêu đề:
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);
}
Và xây dựng , xem các định nghĩa ký hiệu:
sản xuất .so:
g++-4.8 -shared src/shared.cpp -o libshared.so -I include/ -fPIC
biên dịch và liên kết chính:
g++-4.8 src/main.cpp -I include/ -lshared -L.
biểu tượng được đánh dấu là "độc đáo":
nm -C -A *.so a.out | grep 'TemplatedClassWithStatic<int>::value'
libshared.so:0000000000200a70 u TemplatedClassWithStatic<int>::value
a.out:00000000006012b0 u TemplatedClassWithStatic<int>::value
sản xuất .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
biên dịch và liên kết chính
~/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
ký hiệu yếu!
nm -C -A *.so a.out | grep 'TemplatedClassWithStatic<int>::value'
libshared.so:00002004 V TemplatedClassWithStatic<int>::value
a.out:00068000 V TemplatedClassWithStatic<int>::value
Chỉnh sửa, ghi chú cho bối cảnh: Tôi đã chơi với OOLua, thư viện giúp ràng buộc C++ để Lua và unittests của tôi đã thất bại khi tôi bắt đầu để nhắm mục tiêu Android. Tôi không "sở hữu" mã và tôi muốn thay đổi nó một cách sâu sắc.
Chỉnh sửa, để chạy nó trên Android:
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
Cảm ơn. Tôi có nên kết luận rằng chuỗi công cụ Android không hỗ trợ tiêu chuẩn C++ hoàn toàn miễn là bạn bắt đầu sử dụng thư viện được chia sẻ? – Joky
"Chuỗi công cụ Android không hỗ trợ chuẩn C++ miễn là bạn bắt đầu sử dụng thư viện chia sẻ" --- thử nghiệm của riêng tôi với các ký hiệu yếu (trên Linux) cho thấy chúng thực sự làm việc cho dữ liệu tĩnh trên các thư viện được chia sẻ. Tức là, trình liên kết sẽ chỉ buộc một trong các ký hiệu yếu được sử dụng, các trường hợp khác sẽ bị bỏ qua. Bạn đã thử chạy chương trình của mình chưa? –
Có, địa chỉ được in khác nhau (chỉ trên Android) – Joky