2016-11-22 25 views
1

C++參考說:http://en.cppreference.com/w/cpp/atomic/atomic的std ::原子平凡能夠複製結構

std::atomic may be instantiated with any TriviallyCopyable type T

然而下面的示例下的g ++ 6.2.0

#include <atomic> 
#include <functional> 

struct Test11 { 
    int x; 
}; 
struct Test12 { 
    char x; 
}; 
struct Test13 { 
    long x; 
}; 
struct Test2 { 
    char x; 
    int y; 
}; 
struct Test3 { 
    int y; 
    long x; 
}; 

template<typename T, typename... ARGS> 
void test(ARGS&& ... args) { 
    static_assert(std::is_trivially_copyable<T>::value); 

    std::atomic<T> a; 
    a.store(T{std::forward<ARGS>(args)...}); 
} 

int main() { 
    test<Test11>(1); 
    test<Test12>('\1'); 
    test<Test13>(1L); 
    test<Test2>('\1',2); 
    test<Test3>(1,2L); 
    return 0; 
} 

編譯不起作用:g++-6 -std=c++14 -latomic test.cpp

/tmp/cchademz.o: In function std::atomic<Test3>::store(Test3, std::memory_order) : test.cpp:(.text._ZNSt6atomicI5Test3E5storeES0_St12memory_order[_ZNSt6atomicI5Test3E5storeES0_St12memory_order]+0x3e): undefined reference to __atomic_store_16 collect2: error: ld returned 1 exit status

g++-6 --version

g++ (Ubuntu 6.2.0-7ubuntu11) 6.2.0 20161018

特別是我不明白爲什麼Test2有效,但Test3沒有。

任何想法?

編輯:添加-latomic標誌和g ++版本

+2

您是否嘗試在編輯行末尾添加'-latomic'偶然?代碼使用'-latomic'(g ++ 6.2)編譯coliru:http://coliru.stacked-crooked.com/a/fd421bd3d1715897 – Holt

+0

您可以嘗試使用代替嗎? –

+0

將'-latomic'移動到最後工作。但爲什麼? – WaeCo

回答

4

正如其現已刪除answer提及@TartanLlama,你需要對libatomic鏈接:

g++-6 -std=c++14 test.cpp -latomic 

您需要添加-latomic在編輯線的末尾。如果您在test.cpp之前放置-latomic(例如Colidu上的g++),某些編譯器(鏈接器)可能會正常工作,但有些編譯器不會(請參閱Why does the order in which libraries are linked sometimes cause errors in GCC?)。

免責聲明:我不是在連鎖方面的專家,所以我不能提供詳細的解釋,爲什麼它與-latomic適用於某些平臺之前,而不是在其他(我猜接頭是不同的,但.. )。


至於爲什麼,如果你刪除Test3您的代碼編譯,這是編譯器和體系結構相關。如果你看看與-O2g++6.2生成的ASM上godbolt

sub  rsp, 24 
movabs rax, 8589934593 
mov  ecx, 5 
mov  DWORD PTR [rsp], 1 
mov  rdi, rsp 
mov  esi, 1 
mov  edx, 2 
mfence 
mov  BYTE PTR [rsp], 1 
mfence 
mov  QWORD PTR [rsp], 1 
mfence 
mov  QWORD PTR [rsp], rax 
mfence 
call __atomic_store_16 

你看到的結構需要不到8個字節(Test1XTest2),編譯器可以使用mov QWORD指令(四字在現今的體系結構中通常是8個字節),但是它不能產生單個指令來處理尺寸嚴格大於8的情況(sizeof(Test3)通常是16)。

基本上,有可能是一個std::atomic<T>專業化(或std::atomic<T>一些操作的)中g++T爲「小」,並且定義「小」是可能的體系結構相關的。

免責聲明:再次,我不是關於<atomic>的專家,所以這是主要是從對有關與godbolt的g++clang上Coliru行爲產生的ASM實驗。

clang具有__atomic_store_8過程和__atomic_store過程,並且在不-latomic它不會編譯Test2Test3。然而,即使sizeof(Test13)是8,它仍然設法編譯,所以它對某些結構不使用__atomic_store_8icc有完全不同的行爲,並且不會生成任何call(無法在Coliru上測試,但可以在godbolt上查看)。