2015-03-07 3 views
5

das folgende Stück Code vor:Wie kommt es, dass std :: atomic <double> nicht implementiert ist, wenn mit clang kompiliert wird?

#include <atomic> 

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

G ++ kompiliert es in Ordnung nur während Klirren ++ folgendes produziert:

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) 

Sie verknüpfen sie nicht gegen den gleichen Standard-Bibliothek?

+2

Meistens verwendet clang libC++, während gcc libstdC++ verwendet. –

+1

Wenn Sie also mit Clang auf einem System kompilieren, auf dem nur die GCC-Standardbibliothek installiert ist, müssen Sie wahrscheinlich das Flag "-lstdC++" an Clang übergeben. – 5gon12eder

+0

Ja, 'clang ++ -std = C++ 11 -lstdC++ Main.cpp' kompiliert tatsächlich das Programm. Es ist also eine Sache von 'libC++', das Feature nicht implementiert zu haben, während 'libstdC++' es hat? – Rovanion

Antwort

1

Wenn clang++ -stdlib=libstdc++ Ihr Problem nicht löst, verknüpfen Sie mit -latomic für die Implementierung dieser Funktionen.

Versuchen Sie, Ihren Compiler zu Inline-8-Byte- und engeren Atomics zu bekommen, da die Bibliotheksfunktionen möglicherweise große Nachteile haben.

Beachten Sie, dass die Bibliotheksfunktionen nicht unterstützen einen Speicher schwächer als memory_order_seq_cst Bestellung, so dass sie immer Verwendung mfence auf x86, auch wenn die Quelle relaxed verwendet.

Die 32-Bit-x86-Version von __atomic_store_8 ist noch schlimmer: Es verwendet lock cmpxchg8b anstelle eines SSE oder x87 8-Byte-Speichers. Dies macht es funktioniert, auch wenn es falsch ausgerichtet ist, aber mit einer massiven Leistungseinbuße. Es hat auch zwei redundante lock or [esp], 0 Anweisungen als zusätzliche Barrieren um seine Argumente vom Stapel zu laden. (Ich bin bei /usr/lib32/libatomic.so.1.2.0 von gcc7.1.1 auf Arch Linux suchen.)

Ironischerweise aktuelle gcc -m32 (in C11-Modus nicht C++ 11) unter ausrichtet atomic_llong innerhalb einer Struktur, aber inlines movq xmm Lasten/speichert, also ist es nicht wirklich atomar. (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65146#c4)

Current Klirren -m32 atomic_llong zu 8 Byte sogar innerhalb structs ausrichtet (im Gegensatz zu regulären long long, die der i386 System V ABI richtet sich nur auf 4B). Die Ironie ist, dass Clam Aufrufe an die Bibliotheksfunktionen generiert, die eine lock cmpxchg8b verwenden, so dass sie sogar bei Cache-Zeilenaufteilungen atomar ist. (Why is integer assignment on a naturally aligned variable atomic?). Daher ist clang sicher, selbst wenn irgendein gcc-kompilierter Code ihm einen Zeiger auf eine fehlausgerichtete _Atomic long long übergibt. Aber es stimmt nicht überein mit gcc über Struktur-Layout, so dass dies nur helfen kann, wenn es einen Zeiger auf die atomare Variable direkt erhält, anstatt die umgebende Struktur.

+0

FWIW, -latomic hat geholfen (ubuntu 17.04, clang 5.0.1-m32, alle gcc-multilib etc. installiert). –

Verwandte Themen