У меня странная проблема, которая возникает во время связывания.
У меня есть заголовочный файл, содержащий следующее определение foo.hpp
:
struct Foo { static __thread int x; }
И исходный файл, который ссылается на эту переменную plugin.cpp
:
#include "foo.hpp"
void bar() { int y = Foo::x; }
Он отлично компилируется с:
$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -fPIC -o plugin.cpp.o -c plugin.cpp
Но когда я пытаюсь связать динамическую библиотеку:
$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -dynamiclib -Wl,-undefined,dynamic_lookup -o libext.dylib ext.cpp.o
Я получил:
ld: недопустимая ссылка локальной переменной потока на обычный символ __ZN3Foo1xE для архитектуры x86_64
Однако байт-код llvm подразумевает, что компилятор правильно видит Foo::x
как переменную TLS.
$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -fPIC -S -emit-llvm -o -
... omitted
@_ZN3Foo1xE = external thread_local global i32
... omitted
; Function Attrs: nounwind ssp uwtable
define hidden void @_Z3barv() #0 {
%y = alloca i32, align 4
%1 = load i32* @_ZN3Foo1xE, align 4
store i32 %1, i32* %y, align 4
ret void
}
Что может быть причиной этой проблемы с компоновщиком и есть ли обходной путь? Я не могу найти никаких сообщений об ошибках, связанных с этим.
Примечания:
- Это чисто использование Apple LLVM 7.0.0
- У меня нет проблем с подключением с помощью gcc 5 или gcc 4.9.3 в OS X.
EDIT Та же проблема возникает при ссылке на глобальную (вместо статического класса) переменную.
Когда я использую thread_local
вместо __thread
, это работает нормально, однако thread_local
не работает с версией LLVM, поставляемой с Xcode.
Foo::x
глобальной переменной? Если это работает, вы можете оставить его глобальным или сделать его локальным (статическое или анонимное пространство имен) для foo.cpp со статической функцией получения вFoo
. Я просто предполагаю; возможно, у компилятора проблема со статическими переменными-членами __thread. - person 1201ProgramAlarm   schedule 14.12.2015extern __thread int my_global;
- person Joel Cornett   schedule 14.12.2015thread_local
в clang 7. - person Joel Cornett   schedule 14.12.2015thread_local
. Если бы мне пришлось угадывать, я бы сказал, что__thread
является одной из этих версий-предшественников и на самом деле не работает в контексте DLL. Если это так, сообщение об ошибке на самом деле говорит вам, что цепочка инструментов не поддерживает ваше использование. - person eh9   schedule 14.12.2015__thread
должны быть статически инициализированы (действительно, компилятор жалуется, если конструкторconstexpr
не используется при инициализации переменных__thread
для агрегатных типов). Чтобы дать больше информации, фактический вариант использования заключается в том, что определение переменной находится в отдельно скомпилированном двоичном файле и доступно для плагинов (которые видят объявление в файле заголовка, как в вопросе). Кажется, не имеет значения, объявлены ли переменные глобальноextern
s или помещены в пространство имен для класса, и, как я уже говорил ранее, связывание отлично работает с использованием gcc. - person Joel Cornett   schedule 14.12.2015__thread
менее обширно, чем gcc: / К сожалению, я не могу найти никакой документации, устраняющей это несоответствие. - person Joel Cornett   schedule 14.12.2015__thread
в LLVM не совпадает с__thread
в GCC; ни один из них не является стандартным. - person eh9   schedule 14.12.2015