This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: linker fails with multiple definitions after inline thread_local var within class


I notice that you are not independently compiling your source files and have no
include guard in t.h.
Could I suggest that you add the include guard to t.h and retest.
If you still have an issue, try independently compiling your source files, then
linking them as a separate step, to see if that works.
You could also test reproducing the issue on another gcc platform, under a Unix
VM, or a WSL Linux distro.

I attach a versiuon of the test with an include guard and with t1.cpp and t2.cpp compiled in separate invocations of g++ - I still see the multiple definition.

${1:-g++} -std=c++17 -I. -c t1.cpp
${1:-g++} -std=c++17 -I. -c t2.cpp
${1:-g++} -std=c++17 t1.o t2.o -o t
/usr/lib/gcc/x86_64-pc-cygwin/8.3.0/../../../../x86_64-pc-cygwin/bin/ld: t2.o:t2.cpp:(.text+0x86): multiple definition of `TLS init function for Data::valref'; t1.o:t1.cpp:(.text+0x4a): first defined here
collect2: error: ld returned 1 exit status
./t

As per my original posting before enquiring here I had tried on a 64-bit ubuntu machine, on a Macbook (where it is clang not g++, but I invoke the compiler as g++) and on a Raspberry pi.

The original code I had pain with was with include guards and all files compiled independently via make - the test casee I submitted had perhaps tried to hard to shorten and simplify.

I also tried both 32 and 64-bit mingw compilers under cygwin - making that easier is why the test script goes ${1:-g++} so I can override the compiler selection to be x86_64-w64-mingw32-g++ or the i686 variant. Those both show the multiple definition problem.


I had also spent some time trying to check in a file c++17-draft-standard.pdf and doing web research on rules regarding static thread_local fields in classes. There is plenty to alert me to the fact that I need to be vary sensitive to issues about exactly when initializers get invoked and in which order, and I spent some time trying to convince myself I had my mind clear on that - but anyway even if I was wrong on that count it would not cause multiple-definitions and linker failure. But I have tried reading up and thinking about initialization order too, but that is not the issue in this query!

I have also experimented with g++ options such as -ftls-model=... and -mtls-dialect and not observed any altering the gross behavior.

So at present the cygwin g++, i686-w32-mingw32-g++ and x86_64-w64-mingw32-g++ are the cases where this linker clash arises for me but no others, and I have failed to achieve a web-search explaining this as a valid limitation. But I am painfully aware that the C++ standard is complicated enough that I could have missed spottting a paragraph and that my web-searches may not have found the correct keywords to use!

You would have to check the C++17 standard, gcc docs, and/or mailing list, or
bugzilla, to see if using that feature in that manner is supported, or if there
are issues, limitations, or restrictions on doing so.

My practical response to this clearly has to be to work around it - but it still seems proper to alert cygwin people to a potential issue on their platform! The relevant code in my real example already conditionalizes on whether the C++ compiletr being used does or does not claim to support inline variables and whether or not it is liable to be on top of Windows - I want it to build and run happily for others more or less regardless - but I am also fairly fussed about performance (which is a reason for C++ not Java, Python etc etc!).


It may be more useful to ask about such language/build interaction issues first
on forums such as StackOverflow and/or language mailing lists, before posting
here, as Cygwin and gcc are implemented in C++, so most issues are likely to
have been noticed and fixed, but language/build issues are not often discussed,
as all support is from volunteers, and language issues are off topic.

Thank you - that is useful and I will try again directly with gcc-central. It looks as if even if this issue mainly hits on Cygwin that there are at least not a lot of others who have experienced it and felt like jumping in.

There may be little response here unless someone has encountered the same issue
using the same features.

General points:

Support by gcc of standards often lags; library feature support is dependent on
libstdc++, newlib, and Cygwin winsup; and the Cygwin gcc release is a couple of
versions behind the head/tip:

Accepted. But __cpp_inline_variables being defined is advertising support for same! And the gcc page you cite below declares it ok from gcc 7 onwards, and indeed I had looked at the first one!

https://gcc.gnu.org/projects/cxx-status.html#cxx17
https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2017



Specifying the language standard -std=c++17 requires your sources to be strictly
conforming, as it disables a lot of the GNU, POSIX, and Cygwin features and
support that extend and relax the standards, sometimes with GNU rather than
standard semantics, with issues, limitations, or restrictions, or may not yet be
available.

-std=c++17 and -std=gnu++17 does not change things for me. Indeed my original project was using gnu++17 but to report it I dropped back to -std=c++11 and dropped the -Wall (which does not moan about anything).

Features may not work, and may not issue a diagnostic, if that is not required,
or just not yet implemented, perhaps dependent on support in binutils or other
parts of the tool chain.

Agreed and accepted quite happily. And it is pretty clear that implementing thread-local on less that helpful platforms involved a deal of pain - the Windows native scheme used in a naive way may not help with destructors and linker support for you is "interestingly" different from that for Linux etc.

I think I hope for two things - the first is to see if my code violated some part of the C++ specification that I have not found and hence the tool-chain is entitled to reject it. I tried doing my homework first but the C++ specification is Big and Complicated! The second is that if this is an issue that it has been reported so that it can get addressed in due course.

Thank you!   Arthur

Attachment: tltest.sh
Description: Binary data

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]