Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static *template* class member across dynamic library

Edit: the comments below the accepted answer show that it might be an issue with the Android dynamic loader.

I have a header for a template class with a static member. At runtime the address of the static member is used in the library and in the client code. The template is implicitly instantiated both in the library and in the client code. It works fine on Linux and OSX, the symbol is duplicated but marked as "uniqued" as shown by nm (see below). However when I compile for ARM (Android), the symbol is marked weak in both the DSO and the executable. The loader does not unify and the symbol is effectively duplicated at runtime!

I read these: two instances of a static member, how could that be? Static template data members storage and especially this answer: https://stackoverflow.com/a/2505528/2077394 and: http://gcc.gnu.org/wiki/Visibility

but I am still a little bit puzzled. I understand that the attributes for visibility helps to optimize, but I thought it should work by default. I know the C++ standard does not care about shared library, but does it means that using shared libraries breaks the standard? (or at least this implementation is not C++ standard conform?) Bonus: how can I fix it? (and not using template is not an acceptable answer:))

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);
}

And building, looking at the symbols definitions:

producing .so:

 g++-4.8  -shared src/shared.cpp  -o libshared.so -I include/ -fPIC

compiling and linking main:

 g++-4.8 src/main.cpp -I include/ -lshared -L.

symbols are marked as "unique":

nm -C -A *.so a.out | grep 'TemplatedClassWithStatic<int>::value'
libshared.so:0000000000200a70 u TemplatedClassWithStatic<int>::value
a.out:00000000006012b0 u TemplatedClassWithStatic<int>::value

producing .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

compiling and linking main

~/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

symbols are weak!

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, note for the context: I was playing with OOLua, a library helping binding C++ to Lua and my unittests were failing when I started to target Android. I don't "own" the code and I would rather modifying it deeply.

Edit, to run it on 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
like image 616
Joky Avatar asked Apr 24 '14 06:04

Joky


1 Answers

Android does not support unique symbols. It is a GNU extension of ELF format that only works with GLIBC 2.11 and above. Android does not use GLIBC at all, it employs a different C runtime called Bionic.

(update) If weak symbols don't work for you (end update) I'm afraid you would have to modify the code such that it does not rely on static data.

like image 95
n. 1.8e9-where's-my-share m. Avatar answered Oct 03 '22 15:10

n. 1.8e9-where's-my-share m.