C ++ 11:GCC 4.8静态thread_local std :: unique_ptr未定义引用 [英] C++11: GCC 4.8 static thread_local std::unique_ptr undefined reference

查看:384
本文介绍了C ++ 11:GCC 4.8静态thread_local std :: unique_ptr未定义引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要为将通过宏访问的每个线程存储唯一的指针.我以为我应该使用单例和静态thread_local std :: unique_ptr对象解决此问题.这是代码的简化版本:

I need to store a unique pointer for every thread that will be accessed through a macro. I thought I should solve this with a singleton and static thread_local std::unique_ptr objects. Here is a simplified version of the code:

#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;

如果我使用gcc 4.8.1进行编译:

If I compile this with gcc 4.8.1:

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

我得到:

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

我希望我可以从clang获得更多信息,但是它在clang 3.4中可以很好地工作:

I was hoping I might get more information from clang, however it works perfectly fine with clang 3.4:

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

运行程序会产生我期望的结果:

And running the program yields the result I was expecting:

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

我不确定自己在做什么错,是否不可能有静态thread_local unique_ptr对象?它可以与int或"naked"指针之类的简单类型一起使用.

I'm not sure what I'm doing wrong here, is it not possible to have static thread_local unique_ptr objects? It works with simple types like int or 'naked' pointers.

这可能是与 http://gcc.gnu.org/相关的错误. bugzilla/show_bug.cgi?id = 55800

解决方法1:使用clang(yay.cpp)编译一个文件

Workaround 1: compile the one file with clang (yay.cpp)

解决方法2(可怕且不可移植):首先将yay.cpp编译为程序集,添加

Workaround 2 (horrible and unportable): compile yay.cpp to assembly first, add

.globl _ZTWN3Yay3yayE
_ZTWN3Yay3yayE = __tls_init

到汇编文件,编译为目标文件,并与其余文件链接

to the assembly file, compile to object file, link with the rest

推荐答案

我通过在Yay.hpp中为Yay定义了什么都不做的ctor进行了实验:

I experimented with this by defining a do-nothing ctor for Yay in Yay.hpp:


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

当我这样做时,错误消息变为:

When I did that, the error message became:


/tmp/cc8gDxIg.o: In function `TLS wrapper function for Yay::yay':
main.cpp:(.text._ZTWN3Yay3yayE[_ZTWN3Yay3yayE]+0x5): undefined reference to `TLS init function for Yay::yay'

这导致我发现 GCC错误55800 .该错误存在于GCC 4.8.2之前的版本中,并已在4.8.3和4.9中修复.在讨论线程中,我在重复的 GCC错误59364 中找到了使不回端口修复程序.因此,在升级到4.9之前,您的汇编器黑客似乎是唯一可用的解决方案.

That led me to GCC bug 55800. The bug exists in GCC versions up through 4.8.2, and is fixed in 4.8.3 and 4.9. In discussion threads I found on duplicate GCC bug 59364, the decision has been made not to back port the fix. Therefore, your assembler hack appears to be the only solution available until you move to 4.9.

这篇关于C ++ 11:GCC 4.8静态thread_local std :: unique_ptr未定义引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆