2015-03-07 24 views
5

Hãy xem xét các đoạn mã sau:Làm thế nào đến std :: nguyên tử <double> không được thực hiện khi biên dịch với tiếng kêu?

#include <atomic> 

int main(void) { 
    std::atomic<double> aDouble; 
    aDouble = 6.0; 
} 

G ++ biên dịch nó chỉ tốt khi kêu vang ++ sản ​​xuất như sau:

clang++ -std=c++11 Main.cpp 
/tmp/Main-d4f0fc.o: In function `std::atomic<double>::store(double, std::memory_order)': 
Main.cpp:(.text._ZNSt6atomicIdE5storeEdSt12memory_order[_ZNSt6atomicIdE5storeEdSt12memory_order]+0x31): undefined reference to `__atomic_store_8' 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

Họ không liên kết chống lại các thư viện chuẩn giống nhau không?

+2

Chủ yếu là clang sử dụng libC++ trong khi gcc sử dụng libstdC++. –

+1

Do đó, nếu bạn đang biên dịch với Clang trên một hệ thống chỉ cài đặt thư viện chuẩn GCC, bạn có thể cần phải chuyển cờ '-lstdC++' sang Clang. – 5gon12eder

+0

Có, 'clang ++ -std = C++ 11 -lstdC++ Main.cpp' thực sự biên dịch chương trình. Vì vậy, nó là một vấn đề của 'libC++ 'không có thực hiện các tính năng trong khi' libstdC++ 'có nó? – Rovanion

Trả lời

1

Nếu clang++ -stdlib=libstdc++ không giải quyết được sự cố của bạn, hãy liên kết với -latomic để triển khai các chức năng này.

Hãy thử tải trình biên dịch của bạn về nguyên tử 8 byte và hẹp hơn, vì các hàm thư viện có các nhược điểm lớn tiềm ẩn.

Ghi chú rằng chức năng thư viện không hỗ trợ một bộ nhớ đặt hàng yếu hơn memory_order_seq_cst, vì vậy họ luôn sử dụng mfence trên x86, thậm chí nếu nguồn sử dụng relaxed.

Phiên bản 32 bit x86 của __atomic_store_8 thậm chí còn tệ hơn: nó sử dụng lock cmpxchg8b thay vì một cửa hàng 8-byte SSE hoặc x87 8 byte. Điều này làm cho nó hoạt động ngay cả khi nó không chính xác, nhưng tại một hình phạt hiệu suất lớn. Nó cũng có hai hướng dẫn dư thừa lock or [esp], 0 làm các rào cản thêm xung quanh tải đối số của nó từ ngăn xếp. (Tôi nhìn vào /usr/lib32/libatomic.so.1.2.0 từ gcc7.1.1 trên Arch Linux.)

Trớ trêu thay, -m32 gcc hiện tại (trong chế độ C11, không phải C++ 11) dưới Canh lề atomic_llong bên trong một cấu trúc, nhưng inlines movq xmm tải/cửa hàng, vì vậy nó không thực sự nguyên tử. (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65146#c4)

Hiện tại clang -m32 sắp xếp atomic_llong đến 8 byte ngay cả bên trong cấu trúc (không giống như thường lệ long long, mà hệ thống i386 V ABI chỉ căn chỉnh với 4B). Điều trớ trêu là clang tạo ra các cuộc gọi đến các hàm thư viện, sử dụng một số lock cmpxchg8b vì vậy nó thực sự là nguyên tử ngay cả với các phần tách dòng bộ nhớ cache. (Why is integer assignment on a naturally aligned variable atomic?). Vì vậy, clang là an toàn ngay cả khi một số mã gcc biên dịch vượt qua nó một con trỏ đến một sai lệch _Atomic long long. Nhưng nó không đồng ý với gcc về cấu trúc bố trí, do đó, điều này chỉ có thể giúp đỡ nếu nó được một con trỏ đến biến nguyên tử trực tiếp, chứ không phải là cấu trúc có chứa.

+0

FWIW, -latomic đã giúp (ubuntu 17.04, clang 5.0.1 -m32, tất cả gcc-multilib, vv được cài đặt). –

Các vấn đề liên quan