2013-10-17 192 views
13

我需要爲每個將通過宏訪問的線程存儲一個唯一的指針。我以爲我應該用單例和靜態thread_local std :: unique_ptr對象來解決這個問題。下面是代碼的簡化版本:C++ 11:GCC 4.8 static thread_local std :: unique_ptr undefined reference

的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 

我希望我可以得到鐺的更多信息,但它的工作原理與鐺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 obj學分?它適用於簡單類型,如int或「裸」指針。

編輯:

這是可能的,這是關係到http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55800

EDIT2了一個錯誤:

解決方法1:編譯一個文件,鐺(yay.cpp)

解決方法2(可怕和不可移植):首先編譯yay.cpp程序集,然後添加

.globl _ZTWN3Yay3yayE 
_ZTWN3Yay3yayE = __tls_init 

的彙編文件,編譯成目標文件,鏈接,其餘

+0

'getYay()'的預處理器替換是否可能會讓您感到困惑? – Tom

+0

不,如果我直接刪除#define並調用Yay :: getYay(),它不起作用。 – linedot

+0

在您的錯誤報告中,您會看到代碼的簡化版本以及可能的解決方法。也許你可以把它作爲答案。 –

回答

2

我在Yay.hpp定義一個什麼都不做的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版本中存在的bug通過4.8.2,並在4.8.3和4.9中修復。在我發現的重複GCC bug 59364的討論線索中,已做出決定不支持修復。因此,你的彙編程序破解似乎是唯一可用的解決方案,直到你移到4.9。