A static class member should be able to be thread local: class foo { static __thread int i; }; __thread int foo::i = 0; foo bar; If bar.i is used in the same file as where bar is instantiated, then bar.i is indeed thread-local. However, if bar.i is used in another file, then it is not. This appears to be a bug. Assuming I manage to attach the testcase to this report: The testcase contains 3 source files: __thread.hpp, __thread.cpp defining foo(), __threadmain.cpp defining main(). Build a.out using the supplied Makefile. __thread.hpp declares 2 classes, class Encap and template wrapper Templ. Both contain static thread-local members. __threadmain.cpp instantiates 3 objects: one a thread-local POD, one of Encap, one using Templ. Its main() creates threads running function foo(). __thread.cpp foo() sets the POD and thread-local values of the Encap instance and Templ instance to the thread id. It outputs the thread-local values and their addresses at the start of foo() and end of foo(). In the test case, only the POD appears to be thread-local. The Encap instance and Templ instance are not. The file a.1 shows that, as foo() exits in the different threads, the thread-local values are incorrect. Not surprising, as the address of each of the thread-local members of Encap and Templ are the same. This is a bug. If the instantiations of Encap and Templ are moved from __threadmain.cpp to __thread.cpp (where foo() is defined and the instances are used), then all are thread-local. The addresses of each of the thread-local members of Encap and Templ are different, as I would expect. This is correct. This is on rh9. llama 200> gcc -v Reading specs from /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/specs Configured with: ../configure --enable-shared --enable-threads=posix --with- system-zlib --enable-__cxa_atexit Thread model: posix gcc version 3.3.2 llama 201> ld -v GNU ld version 2.13.90.0.18 20030206 llama 202> as -v GNU assembler version 2.13.90.0.18 (i386-redhat-linux) using BFD version 2.13.90.0.18 20030206 llama 203> uname -a Linux llama 2.4.20-28.9smp #1 SMP Thu Dec 18 13:37:36 EST 2003 i686 i686 i386 GNU/Linux Note that the Solaris CC 5.5 compiler does the right thing.
Created attachment 5473 [details] test case Attached is a test case to demonstrate the bug. The test case is described in the bug comment.
Created attachment 5506 [details] Two thread, one static variable, three addresses:)) Try to compile this little program and you'll some funny behaviour.
(In reply to comment #2) > Created an attachment (id=5506) > Two thread, one static variable, three addresses:)) > > Try to compile this little program and you'll some funny behaviour. The is the output on g++ 3.3.2 on debian: __display value: 0x804a058, address: 0x8049c68 in thread 1085393872 __display value: (nil), address: 0x40b1cbc8 in thread 1085393872 disp (nil) __display value: 0x804c3f8, address: 0x8049c68 in thread 1085393872 __display value: (nil), address: 0x40b1cbc8 in thread 1085393872 __display value: 0x804b090, address: 0x8049c68 in thread 1077004064 __display value: (nil), address: 0x4031c718 in thread 1077004064 disp (nil) Erreur de segmentation
This is not a gcc bug, this is a bug in glibc.
(In reply to comment #4) > This is not a gcc bug, this is a bug in glibc. Thanks. Do I have to do something to report it to the glibc maintainers or is the issue already known by them?
You may want to post to the glibc bug reporting list. W.
Why are you so sure it is not a GCC bug? It clearly is a C++ frontend bug: grep -C1 _ZN5TemplImE2_tE __thread.s __threadmain.s __thread.s- movq -16(%rbp), %rax __thread.s: movq %rax, _ZN5TemplImE2_tE(%rip) __thread.s- leave -- __thread.s- movq %rdi, -8(%rbp) __thread.s: movq _ZN5TemplImE2_tE(%rip), %rax __thread.s- leave -- __thread.s- movq (%rax), %rax __thread.s: movq $_ZN5TemplImE2_tE, (%rsp) __thread.s- movq %rdx, %r9 -- __thread.s- movq (%rax), %rax __thread.s: movq $_ZN5TemplImE2_tE, (%rsp) __thread.s- movq %rdx, %r9 -- __threadmain.s- .zero 1 __threadmain.s:.globl _ZN5TemplImE2_tE __threadmain.s- .section .tbss __threadmain.s- .align 8 __threadmain.s: .type _ZN5TemplImE2_tE, @object __threadmain.s: .size _ZN5TemplImE2_tE, 8 __threadmain.s:_ZN5TemplImE2_tE: __threadmain.s- .zero 8 As you can see, _ZN5TemplImE2_tE is correctly declared as a .tbss object in __threadmain.s, but __thread.s works with that object as if it wasn't __thread variable.
FYI, I raised this error with glibc with a slightly different attachment. http://sourceware.org/bugzilla/show_bug.cgi?id=1830 has the code Jakub refers to.
*** This bug has been marked as a duplicate of 19450 ***