Vraag C ++ 11: GCC 4.8 static thread_local std :: unique_ptr undefined reference


Ik moet een unieke aanwijzer opslaan voor elke thread die via een macro wordt geopend. Ik dacht dat ik dit moest oplossen met een singleton en static thread_local std :: unique_ptr-objecten. Hier is een vereenvoudigde versie van de code:

main.cpp

#include <thread>
#include <vector>
#include <iostream>
#include <mutex>
using namespace std;

#include "yay.hpp"

mutex coutMutex;

void yay(int id)
{
    int* yayPtr = getYay();

    // I know this is bad
    coutMutex.lock();
    cout << "Yay nr. " << id << " address: " << yayPtr << endl;
    coutMutex.unlock();
}

int main()
{
    vector<thread> happy;
    for(int i = 0; i < thread::hardware_concurrency(); i++)
    {
        happy.push_back(thread(yay, i));
    }

    for(auto& smile : happy)
    {
        smile.join();
    }
    return 0;
}

yay.hpp

#ifndef BE_HAPPY
#define BE_HAPPY

#include <memory>
class Yay
{
    private:
        static thread_local std::unique_ptr<int> yay;
        Yay() = delete;
        Yay(const Yay&) = delete;
        ~Yay() {}
    public:
        static int* getYay()
        {
            if(!yay.get())
            {
                yay.reset(new int);
            }
            return yay.get();
        }
};

#define getYay() Yay::getYay()

#endif

yay.cpp

#include "yay.hpp"

thread_local std::unique_ptr<int>  Yay::yay = nullptr;

Als ik dit compileer met gcc 4.8.1:

g++ -std=c++11 -pthread -o yay main.cpp yay.cpp

Ik krijg:

/tmp/cceSigGT.o: In function `_ZTWN3Yay3yayE':
main.cpp:(.text._ZTWN3Yay3yayE[_ZTWN3Yay3yayE]+0x5): undefined reference to `_ZTHN3Yay3yayE'
collect2: error: ld returned 1 exit status

Ik hoopte dat ik meer informatie van clang zou krijgen, maar het werkt prima met clang 3.4:

clang++ -std=c++11 -pthread -o yay main.cpp yay.cpp

En het uitvoeren van het programma levert het resultaat op dat ik verwachtte:

Yay nr. 2 address: 0x7fcd780008e0
Yay nr. 0 address: 0x7fcd880008e0
Yay nr. 1 address: 0x7fcd800008e0
Yay nr. 3 address: 0x7fcd700008e0
Yay nr. 4 address: 0x7fcd740008e0
Yay nr. 5 address: 0x7fcd680008e0
Yay nr. 6 address: 0x7fcd6c0008e0
Yay nr. 7 address: 0x7fcd600008e0

Ik weet niet zeker wat ik hier mis heb, is het niet mogelijk om statische thread_local unique_ptr-objecten te hebben? Het werkt met eenvoudige types zoals int of 'naked' pointers.

Bewerk:

Het is mogelijk dat dit een bug is die gerelateerd is aan http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55800

Edit2:

Oplossing 1: compileer het ene bestand met clang (yay.cpp)

Oplossing 2 (vreselijk en niet-uitvoerbaar): compileer yay.cpp eerst met de assembly, voeg toe

.globl _ZTWN3Yay3yayE
_ZTWN3Yay3yayE = __tls_init

naar het assembly-bestand, compileer naar object-bestand, link met de rest


13
2017-10-17 16:47


oorsprong


antwoorden:


Ik experimenteerde hiermee door een do-nothing-ctor te definiƫren voor Yay in Yay.hpp:

- Yay () = verwijderen;
+ Yay () {}

Toen ik dat deed, werd de foutmelding:

/tmp/cc8gDxIg.o: In functie `TLS-wrapper-functie voor Yay :: yay ':
main.cpp :(. text._ZTWN3Yay3yayE [_ZTWN3Yay3yayE] + 0x5): ongedefinieerde verwijzing naar `TLS init-functie voor Yay :: yay '

Dat bracht me ertoe GCC-bug 55800. De bug bestaat in GCC-versies tot 4.8.2 en is opgelost in 4.8.3 en 4.9. In discussiethreads die ik op duplicate heb gevonden GCC-bug 59364, de beslissing is genomen om de fix niet te porteren. Daarom lijkt je assembler-hack de enige oplossing die beschikbaar is totdat je naar 4.9 gaat.


2
2018-03-20 16:57