Consider the following C++ source code files =========> testLib.h <=========== #include <stdexcept> #include <iostream> #define DEBUG1(X) std::cout<<X; typedef int IndexType; namespace Upagraha { template<typename X,int Size> class CompileTimeFixedSizeData { protected: X _data[Size]; //!< The storage of the data static IndexType _size; //!< The size of the data. public: CompileTimeFixedSizeData() { DEBUG1("Template value = "<< Size << std::endl); DEBUG1("Static variable value = "<< _size<< std::endl); } virtual ~CompileTimeFixedSizeData() {} }; //setting the value of _size, which is static template<typename X,int Size> IndexType CompileTimeFixedSizeData<X,Size>::_size=Size; /** Create an instance of CompileTimeFixedSizeData and associated functions. */ #define COMPILE_TIME_FIXED_SIZE_DATA_INSTANCE(TYPE,SIZE) \ template class CompileTimeFixedSizeData<TYPE,SIZE>; } =========> testLib.cpp <=========== #include "testLib.h" namespace Upagraha { COMPILE_TIME_FIXED_SIZE_DATA_INSTANCE(double,3) } =========> main.cpp <=========== #include "testLib.h" namespace Upagraha { //extern template class CompileTimeFixedSizeData<double,3>; // FIXME: Uncomment to see a change in behavior } int main() { Upagraha::CompileTimeFixedSizeData<double,3> a; } =========> makefile <=========== #OPTIONS=-rdynamic -fno-implicit-templates -fPIC OPTIONS=-rdynamic -fno-implicit-templates # FIXME: Uncomment the top one to see change in behaviour test:libtestLib.so testLib.h main.cpp g++ $(OPTIONS) $(TOPTIONS) main.cpp -L"${PWD}" -ltestLib -o main libtestLib.so: testLib.cpp testLib.h g++ $(OPTIONS) $(TOPTIONS) -shared testLib.cpp -o libtestLib.so clean: rm main libtestLib.so *~ ==================================== Put the above four files in same the directory and do the following *) make *) export LD_LIBRARY_PATH="$PWD" *) ./main You'll see the output as ===================== Template value = 3 Static variable value = 0 ===================== Now, follow either of the two "FIXME"s and build the program and run to get ===================== Template value = 3 Static variable value = 3 ===================== Why this difference in behaviour in initialisation of static variable Upagraha::CompileTimeFixedSizeData<X,Size>::_size? Could somebody please explain this?
Created attachment 21120 [details] The test case attached To simplify the task of whomsoever who wants to see the behaviour, all the files mentioned in my previous post is packaged in a tar.bz2 file attached here.
You need to use -fPIC for a shared object, so the version without that is not valid.
Subject: Re: Static members not initialised in explicit template instances of library But, as I know, no where is it mentioned to be necessary for static member initialisation. Why should the compiler allow for such a subtle error? Or is this documented somewhere? Besides this issue, I've not faced any other problem in using shared library by not using -fPIC. Could you please point out the necessary implications that I am missing here? On 7 July 2010 14:48, redi at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org> wrote: > > > ------- Comment #2 from redi at gcc dot gnu dot org 2010-07-07 09:18 ------- > You need to use -fPIC for a shared object, so the version without that is not > valid. > >
Well for x86_64 we get an error: /usr/bin/ld: testLib.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
Works for me on the trunk and in 4.3.2. Can you give the output of "gcc -v"?
Subject: Re: Static members not initialised in explicit template instances of library Output of "gcc -v" is given below. I'm using Fedora 13 (with updates till July 24, 2010). The error still persists. =================== Using built-in specs. Target: i686-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux Thread model: posix gcc version 4.4.4 20100630 (Red Hat 4.4.4-10) (GCC) =================== On 25 July 2010 07:43, pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org> wrote: > ------- Comment #5 from pinskia at gcc dot gnu dot org 2010-07-25 02:13 ------- > Works for me on the trunk and in 4.3.2. > > Can you give the output of "gcc -v"? >
I can reproduce this on Fedora 13 using -fpic or -fPIC fixes it (as well as avoiding SELinux "permission denied" errors when loading the shared object)
I should have read the code properly ... if you've suppressed implicit instantiation in main.cpp and you want the explicit instantiation in a shared object to be used I would expect that you need to *either* use -fpic so the instantiation in the .so is used *or* declare the explicit instantiation by uncommenting the "extern template" declaration. So I think the behaviour you're seeing is normal
Closing.