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

时间:2013-10-17 16:47:04

标签: c++ gcc c++11 clang thread-local-storage

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

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

如果我用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它可以完美地运行:

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

运行程序会得到我期望的结果:

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'指针。

编辑:

这可能是与http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55800

相关的错误

EDIT2:

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

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

.globl _ZTWN3Yay3yayE
_ZTWN3Yay3yayE = __tls_init

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

2 个答案:

答案 0 :(得分:3)

我通过在Yay.hpp中为Yay定义一个do-nothing ctor来试验这个:

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

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

/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 bug 55800。该错误存在于GCC版本中直到4.8.2,并在4.8.3和4.9中修复。在我在重复GCC bug 59364上找到的讨论主题中,我们决定不回复修复程序。因此,在转移到4.9之前,您的汇编程序黑客似乎是唯一可用的解决方案。

答案 1 :(得分:0)

对我来说,事实证明我是与app.py链接并将其删除或将其更改为app,问题就消失了。不知道这里到底发生了什么...

我相信我碰到了gcc错误64697,因为它确实是静态的thread_local -std = c ++ 11。它以32位工作,但不是64位?非常奇怪... gcc 8.2.0 mingw w64交叉编译:

createdb.db

原始提示here