к вопросу. Пожалуйста, посмотрите это!

от программа, которая дает segfault.

Есть конечно

#include <iostream>
#include <vector>
#include <memory>

int main() 
{
    std::cout << "Hello World" << std::endl;

    std::vector<std::shared_ptr<int>> y {};  

    std::cout << "Hello World" << std::endl;
}

абсолютно ничего плохого в самой программе. Основная причина segfault зависит от среды, в которой он построен и работает.Фон

В Amazon мы используем систему сборки, которая собирает и развертывает двоичные файлы (

 а такжеlib) вbinпочти машина независимым образом. Для нашего случая это в основном означает, что он развертывает исполняемый файл (созданный из вышеуказанной программы) в а также$project_dir/build/bin/почти все его зависимости (т.е. общие библиотеки) в, Почему я использовал фразу$project_dir/build/lib/"почти" потому что для общих библиотек таких и, возможно, несколько других, исполняемый файл выбирает из системы (то есть изlibc.so, libm.so, ld-linux-x86-64.so.2 ). Обратите внимание, что это/lib64предполагаемый подобрать изlibstdc++ хотя.$project_dir/build/libТеперь я запускаю его следующим образом:

Однако, если я запустил его, не устанавливая

$ LD_LIBRARY_PATH=$project_dir/build/lib ./build/bin/run

segmentation fault

, Работает нормально.LD_LIBRARY_PATHдиагностика

1. лддВот

 информация для обоих случаев (обратите внимание, что я отредактировал вывод, чтобы упомянутьlddполный версия библиотекивезде, где есть разницаи без LD_LIBRARY_PATH:)

$ LD_LIBRARY_PATH=$project_dir/build/lib ldd ./build/bin/run

linux-vdso.so.1 =>  (0x00007ffce19ca000)
libstdc++.so.6 => $project_dir/build/lib/libstdc++.so.6.0.20 
libgcc_s.so.1 =>  $project_dir/build/lib/libgcc_s.so.1 
libc.so.6 => /lib64/libc.so.6 
libm.so.6 => /lib64/libm.so.6 
/lib64/ld-linux-x86-64.so.2 (0x0000562ec51bc000)

2. GDB, когда это segfaults

$ ldd ./build/bin/run

linux-vdso.so.1 =>  (0x00007fffcedde000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6.0.16 
libgcc_s.so.1 => /lib64/libgcc_s-4.4.6-20110824.so.1
libc.so.6 => /lib64/libc.so.6 
libm.so.6 => /lib64/libm.so.6 
/lib64/ld-linux-x86-64.so.2 (0x0000560caff38000)
3. LD_DEBUG = все
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7dea45c in _dl_fixup () from /lib64/ld-linux-x86-64.so.2
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.209.62.al12.x86_64
(gdb) bt
#0  0x00007ffff7dea45c in _dl_fixup () from /lib64/ld-linux-x86-64.so.2
#1  0x00007ffff7df0c55 in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2
#2  0x00007ffff7b1dc41 in std::locale::_S_initialize() () from $project_dir/build/lib/libstdc++.so.6
#3  0x00007ffff7b1dc85 in std::locale::locale() () from $project_dir/build/lib/libstdc++.so.6
#4  0x00007ffff7b1a574 in std::ios_base::Init::Init() () from $project_dir/build/lib/libstdc++.so.6
#5  0x0000000000400fde in _GLOBAL__sub_I_main () at $project_dir/build/gcc-4.9.4/include/c++/4.9.4/iostream:74
#6  0x00000000004012ed in __libc_csu_init ()
#7  0x00007ffff7518cb0 in __libc_start_main () from /lib64/libc.so.6
#8  0x0000000000401021 in _start ()
(gdb)
Я также пытался увидеть информацию компоновщика, включив

 для случая сегфо. Я нашел что-то подозрительное, так как оно ищетLD_DEBUG=all символ, и когда он не может найти это, он дает segfault (это моя интерпретация следующего выходного фрагмента BTW):pthread_onceНо я не вижу никаких

initialize program: $project_dir/build/bin/run

symbol=_ZNSt8ios_base4InitC1Ev;  lookup in file=$project_dir/build/bin/run [0]
symbol=_ZNSt8ios_base4InitC1Ev;  lookup in file=$project_dir/build/lib/libstdc++.so.6 [0]
binding file $project_dir/build/bin/run [0] to $project_dir/build/lib/libstdc++.so.6 [0]: normal symbol `_ZNSt8ios_base4InitC1Ev' [GLIBCXX_3.4]
symbol=_ZNSt6localeC1Ev;  lookup in file=$project_dir/build/bin/run [0]
symbol=_ZNSt6localeC1Ev;  lookup in file=$project_dir/build/lib/libstdc++.so.6 [0]
binding file $project_dir/build/lib/libstdc++.so.6 [0] to $project_dir/build/lib/libstdc++.so.6 [0]: normal symbol `_ZNSt6localeC1Ev' [GLIBCXX_3.4]
symbol=pthread_once;  lookup in file=$project_dir/build/bin/run [0]
symbol=pthread_once;  lookup in file=$project_dir/build/lib/libstdc++.so.6 [0]
symbol=pthread_once;  lookup in file=$project_dir/build/lib/libgcc_s.so.1 [0]
symbol=pthread_once;  lookup in file=/lib64/libc.so.6 [0]
symbol=pthread_once;  lookup in file=/lib64/libm.so.6 [0]
symbol=pthread_once;  lookup in file=/lib64/ld-linux-x86-64.so.2 [0]

 для случая, когда он работает успешно!pthread_onceВопросов

Я знаю, что это очень сложно для отладки, как это, и, вероятно, я не дал много информации о среде и все. Но все же, мой вопрос: что может быть основной причиной этого сегфоута? Как отладить дальше и найти это? Как только я найду проблему, исправить это будет легко.

Компилятор и платформа

я использую

GCC 4.9 на RHEL5.Эксперименты

E # 1Если я прокомментирую следующую строку:

Он компилируется и работает нормально!

std::vector<std::shared_ptr<int>> y {}; 

E # 2

Я просто включил следующий заголовок в мою программу:

и связаны соответственно. Теперь это работает без каких-либо ошибок. Таким образом, кажется, имея зависимость от

#include <boost/filesystem.hpp>

Некоторые требования выполнены или проблема обойдена!libboost_system.so.1.53.0.E # 3

Так как я видел, как это работает, когда я сделал исполняемый файл для связи с

Я сделал следующие шаги шаг за шагом.libboost_system.so.1.53.0Вместо того, чтобы использовать

 в самом коде я использую оригинальный код и запускаю его предзагрузкой#include <boost/filesystem.hpp> с помощьюlibboost_system.so следующее:LD_PRELOADи все прошло успешно!

$ LD_PRELOAD=$project_dir/build/lib/libboost_system.so $project_dir/build/bin/run

Затем я сделал

 наldd который дал список библиотек, две из которых были:libboost_system.soТак что вместо предварительной загрузки

  /lib64/librt.so.1
  /lib64/libpthread.so.0

Я предварительно загружаюlibboost_system а такжеlibrt отдельно:libpthreadВ обоих случаях все прошло успешно.

$ LD_PRELOAD=/lib64/librt.so.1 $project_dir/build/bin/run

$ LD_PRELOAD=/lib64/libpthread.so.0 $project_dir/build/bin/run

Теперь мой вывод заключается в том, что при загрузке либо

 или жеlibrt (или жеlibpthreadобе ), некоторые требования выполнены или проблема обойдена! Тем не менее, я до сих пор не знаю причину проблемы.Параметры компиляции и компоновки

Так как система сборки сложна и есть много опций, которые есть по умолчанию. Поэтому я попытался явно добавить

 используя CMake-lpthread команда, то это сработало, как мы уже видели, чтоsetподжимать оно работает! libpthreadДля того, чтобы увидеть

строить разница между этими двумя случаями (когда-он-работа а такжекогда-то-дает-Segfault), Я построил это вподробный режим мимоходом в GCC, чтобы увидеть этапы компиляции и параметры, которые он фактически передает-v (компилятор) иcc1plus (Линкер).collect2Обратите внимание, что пути были отредактированы для краткости, используя знаки доллара и фиктивные пути.

($ / gcc-4.9.4 / cc1plus -quiet -v -I / a / include -I / b / include -iprefix $ / gcc-4.9.4 / -MMD main.cpp.d -MF main.cpp.od - MT main.cpp.o -D_GNU_SOURCE -D_REENTRANT -D __USE_XOPEN2K8 -D _LARGEFILE_SOURCE -D _FILE_OFFSET_BITS = 64 -D __STDC_FORMAT_MACROS -D __STDC -LIMIT_MACthgmp.mpm-smps_mps_p_DD_SD_MSDSMPS_DF_SDKS_SD_RUS_DB_SD_S_SD_D_S_D_S_S_D_S_S_D_S_S_S_D_S_S_MD_S_D_S_S_S_D_S_S_WD_S_S_DF_S_S_D_D_S $_DF_D_S_D_S $_D_S_D_S $_DF -march = core2 -auxbase-strip main.cpp.o -g -O3 -Wall -Wextra -std = gnu ++ 1y -version -fdiagnostics-color = auto -ftemplate-deep = 128 -fno-operator-names -o -o /tmp/ccxfkRyd.s)

Независимо от того, работает он или нет, аргументы командной строки

 точно так же. Нет разницы вообще. Это не кажется очень полезным.cc1plusРазница, однако, заключается во времени соединения. Вот что я вижу,

для случая, когда это работает$ / gcc-4.9.4 / collect2 -plugin $ / gcc-4.9.4 / liblto_plugin.so:

-plugin-opt = $ / gcc-4.9.4 / lto-wrapper -plugin-opt = -fresolution = / tmp / cchl8RtI.res -plugin-opt = -pass-through = -lgcc_s -plugin-opt = -pass- through = -lgcc -plugin-opt = -pass-through = -lpthread -plugin-opt = -pass-through = -lc -plugin-opt = -pass-through = -lgcc_s -plugin-opt = -pass-through = -lgcc --eh-frame-hdr -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o запустить /usr/lib/../lib64/crt1.o /usr/lib/../lib64/crti.o $ / gcc-4.9.4 / crtbegin.o -L / a / lib -L / b / lib -L / c / lib
-lpthread --as необходимый main.cpp.o -lboost_timer -lboost_wave -lboost_chrono -lboost_filesystem -lboost_graph -lboost_locale -lboost_thread -lboost_wserialization -lboost_atomic -lboost_context -lboost_date_time -lboost_iostreams -lboost_math_c99 -lboost_math_c99f -lboost_math_c99l -lboost_math_tr1 -lboost_math_tr1f -lboost_math_tr1l -lboost_mpi -lboost_prg_exec_monitor -lboost_program_options -lboost_random -lboost_regex -lboost_serialization -lboost_signals -lboost_system -lboost_unit_test_framework -lboost_exception -lboost_test_exe_exe -exe / lgcc_s -lgcc-lpthread -lc -lgcc_s -lgcc $ / gcc-4.9.4 / crtend.o /usr/lib/../lib64/crtn.oКак вы видете,

 упомянуто-lpthreadдважды! Первый (за которым следует-lpthread) является--as-neededотсутствуетдля случая, когда он дает Segfault , Этотолько Разница между этими двумя случаями.Выход из

 в обоих случаяхnm -CИнтересно, что выход

 в обоих случаях одинаково (nm -Cесли вы игнорируете целочисленные значения в первых столбцах).С точки зрения C ++ это выглядит как UB из-за нарушения ODR. Символы стандартной библиотеки, которая использовалась во время компиляции, должны совпадать с символами во время компоновки, что иногда здесь не так. Просто перекомпиляция на целевой машине должна исправить это. Если вы не можете этого сделать, проверьте, какие версии библиотеки совместимы с двоичными файлами, и убедитесь, что на целевой машине установлена ​​и используется такая версия. В качестве альтернативы вы можете попытаться статически связать некоторые библиотеки вместо использования динамического связывания, но вы, вероятно, не можете сделать это для всего.

0000000000402580 d _DYNAMIC
0000000000402798 d _GLOBAL_OFFSET_TABLE_
0000000000401000 t _GLOBAL__sub_I_main
0000000000401358 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
                 U _Unwind_Resume
0000000000401150 W std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_destroy()
0000000000401170 W std::vector<std::shared_ptr<int>, std::allocator<std::shared_ptr<int> > >::~vector()
0000000000401170 W std::vector<std::shared_ptr<int>, std::allocator<std::shared_ptr<int> > >::~vector()
0000000000401250 W std::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > >::~vector()
0000000000401250 W std::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > >::~vector()
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
0000000000402880 B std::cout
                 U std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
0000000000402841 b std::__ioinit
                 U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
                 U operator delete(void*)
                 U operator new(unsigned long)
0000000000401510 r __FRAME_END__
0000000000402818 d __JCR_END__
0000000000402818 d __JCR_LIST__
0000000000402820 d __TMC_END__
0000000000402820 d __TMC_LIST__
0000000000402838 A __bss_start
                 U __cxa_atexit
0000000000402808 D __data_start
0000000000401100 t __do_global_dtors_aux
0000000000402820 t __do_global_dtors_aux_fini_array_entry
0000000000402810 d __dso_handle
0000000000402828 t __frame_dummy_init_array_entry
                 w __gmon_start__
                 U __gxx_personality_v0
0000000000402838 t __init_array_end
0000000000402828 t __init_array_start
00000000004012b0 T __libc_csu_fini
00000000004012c0 T __libc_csu_init
                 U __libc_start_main
                 w __pthread_key_create
0000000000402838 A _edata
0000000000402990 A _end
000000000040134c T _fini
0000000000400e68 T _init
0000000000401028 T _start
0000000000401054 t call_gmon_start
0000000000402840 b completed.6661
0000000000402808 W data_start
0000000000401080 t deregister_tm_clones
0000000000401120 t frame_dummy
0000000000400f40 T main
00000000004010c0 t register_tm_clones
 sbabbi15 нояб. 2017 г., 22:15
ошибка выглядит подозрительно похожим ...Учитывая точку сбоя и тот факт, что предварительная загрузка
 Nawaz09 нояб. 2017 г., 14:48
 (что по умолчанию в настройках сборки, которые я наследую). Тем не менее, так как мой код не использует какие-либо-pthreadусловное обозначение изкомпоновщик не добавляет его в исполняемый файл. Так жеlibpthreadпоиск за в выводе LD_DEBUG, кажется, красная сельдь, поскольку он не там, когда он работает успешно. Это означает, что это даже не нужно. (pthread_once путь должен бытьrunpools кстати, отредактировал вопрос).$project_dir/build/bin/runПросто несколько случайных мыслей:
 nwp09 нояб. 2017 г., 14:23
Просто несколько случайных мыслей:
 sbabbi11 нояб. 2017 г., 19:12
 требуется для инициализации статической переменной, вероятно, необходимоpthread_once, Это часть языковой поддержки C ++ 11, ее можно отключить / включить с помощьюlocaleЕсть ли шанс, что вы используете золотой компоновщик? Этот-f(no)threadsafe-statics.
 Amadeus09 нояб. 2017 г., 14:34
 вpthread_once, Если вы компилируете свою программу сlibthread вариант, это решает проблему? Вы сказали, что в том числе-pthread решил вашу проблему, но обратите внимание, чтоlibboost_system.so.1.53.0 связано сlibboost_system.so.1.53.0, От следа, который вы предоставляете,libpthread находится в списке доступных для поиска файлов. Вопрос:build/private/builds/RelWithDebInfo/runpools должен быть связан сrunpools@Amadeus: я компилирую свой код сlibphtreads?

Ответы на вопрос(2)

 Linux 5, поэтому не совсем понятно, что вы там используете (DTS 3?).libstdc++Известно, что реализация локали довольно чувствительна к несовпадениям ABI. Смотрите эту ветку в списке gcc-help:

Бинарная совместимость между старым статическим libstdc ++ и новым динамическим

плюс последующие мероприятия в следующем месяцеЛучше всего выяснить, какие биты

 где связаны, где, и каким-то образом достичь согласованности (либо путем скрытия символов, либо перекомпиляции вещей, чтобы они были совместимы).libstdc++Также может быть полезно исследовать модель гибридной связи, используемую для

 в наборе инструментов разработчика Red Hat (где новые биты связаны статически, но основная часть стандартной библиотеки C ++ использует существующий системный DSO), но системаlibstdc++ в Red Hat Enterprise Linux 5 может быть слишком стар для этого, если вам нужна поддержка текущих языковых функций.libstdc++Что ты имеешь ввиду

 Nawaz15 нояб. 2017 г., 17:51
Параметры компиляции и компоновки к вопросу. Пожалуйста, посмотрите это!Ошибка при объявлении переменной типа vector <shared_ptr <int >
 Nawaz10 нояб. 2017 г., 06:03
«GCC 4.9 не является системным компилятором в Red Hat Enterprise Linux 5»? Вы имели в виду не построен дляGCC 4.9 и таким образом это может не работать там должным образом? Не могли бы вы подробнее остановиться на этом, так как это кажется важным моментом?RHEL5Изначально Red Hat Enterprise Linux поставлялась с GCC 4.1, с GCC 4.4 в качестве опции (в форме
 Florian Weimer10 нояб. 2017 г., 09:13
 пакет). Это неgcc44это важно, но это предполагает, что вы можете столкнуться с проблемами ABI, потому что вы используете несколько компиляторов, которые не были построены таким образом, чтобы они создавали совместимые двоичные файлы.Добавили
Решение Вопроса

  это исправить, я считаю, что исполнение этих двух дел расходится вlibpthread, Вот выдержка из кода:locale_init.cc:315 возвращает true, если ваша программа связана с pthread, в частности она проверяет,

  void
  locale::_S_initialize()
  {
#ifdef __GTHREADS
    if (__gthread_active_p())
      __gthread_once(&_S_once, _S_initialize_once);
#endif
    if (!_S_classic)
      _S_initialize_once();
  }

__gthread_active_p() доступен. В моей системе этот символ определен в "/usr/include/c++/7.2.0/x86_64-pc-linux-gnu/bits/gthr-default.h" какpthread_key_createследовательно, это потенциальный источник нарушения ODR.static inlineЗаметить, что

 всегда будет вызыватьLD_PRELOAD=libpthread,so вернуть истину.__gthread_active_p() еще один встроенный символ, который всегда должен

__gthread_onceТрудно догадаться, что происходит без отладки, но я подозреваю, что вы попали в истинную ветвьpthread_once.

 даже тогда, когда это не должно произойти, и программа завершает работу, потому что нет__gthread_active_p() звонить.pthread_onceРЕДАКТИРОВАТЬ

: Так что я провел несколько экспериментов, единственный способ увидеть сбой в еслиstd::locale::_S_initialize возвращает истину, но__gthread_active_p не связан в.pthread_oncelibstdc ++ не ссылается напрямую на

, но он импортирует половинуpthread как слабые объекты, что означает, что они могут быть неопределенными и не вызывать ошибку компоновщика.pthread_xxОчевидно, что связывание pthread приведет к исчезновению аварии, но если я прав, главная проблема заключается в том, что ваш

 считает, что он находится внутри многопоточного исполняемого файла, даже если мы не связывали pthread в.libstdc++В настоящее время,

 использования__gthread_active_p решить, есть ли у нас темы или нет. Это определяется в вашем исполняемом файле как слабый объект (может иметь значение nullptr и все еще в порядке). Я на 99% уверен, что этот символ есть из-за__pthread_key_create (удали его и проверьshared_ptr еще раз чтобы быть уверенным). Итак, как-тоnm привязывается к действительному адресу, возможно из-за этого последнего__pthread_key_create в ваших флагах компоновщика. Вы можете проверить эту теорию, поставив точку останова на-lpthread и проверка, какую ветку вы берете.locale_init.cc:315EDIT2

Резюме комментариев, проблема воспроизводима только если у нас есть все следующее::

использование

 вместоld.goldиспользованиеld.bfdВынужденное слабое определение--as-neededв этом случае посредством__pthread_key_createНе ссылается наstd::shared_ptr.или ссылкаpthreadпослеpthread Чтобы ответить на вопросы в комментариях: --as-needed.

Почему он использует золото по умолчанию?

По умолчанию он использует

, который в большинстве дистрибутивов является символической ссылкой на/usr/bin/ld или же/usr/bin/ld.bfd, Такое значение по умолчанию можно изменить с помощью/usr/bin/ld.gold, Я не уверен, почему в вашем случае этоupdate-alternativesнасколько я понимаю RHEL5 поставляется сld.gold по умолчанию.ld.bfdИ почему gold не добавляет зависимость pthread.so в двоичный файл, если он необходим?

Потому что определение того, что нужно, как-то нечетко.

 говорит (выделение мое):man ld--по мере необходимости

--no-по мере необходимости

Этот параметр влияет на теги ELF DT_NEEDED для динамических библиотек, упомянутых в командной строке

после - как нужная опция. Обычно компоновщик добавляет тег DT_NEEDED для каждой динамической библиотеки, упомянутой в командной строке, независимо от того, нужна ли библиотека на самом деле или нет. --as-required заставляет тэг DT_NEEDED быть выданным только для библиотеки, которая в этой точке ссылки удовлетворяетнеслабый неопределенный символ ссылка из обычного объектного файла или, если библиотека не найдена в списках DT_NEEDED других необходимых библиотек, неслабая неопределенная ссылка на символ из другой необходимой динамической библиотеки. Объектные файлы или библиотеки, появляющиеся в командной строке после рассматриваемой библиотеки, не влияют на то, рассматривается ли библиотека как нужная. Это похоже на правила извлечения объектных файлов из архивов. --no-as-required восстанавливает поведение по умолчанию.Теперь согласно

этот отчет об ошибке чествует часть "неслабый неопределенный символ", в то время как, gold видит слабые символы по мере необходимости. TBH У меня нет полного понимания по этому поводу, и есть некоторая дискуссия по этой ссылке относительно того, следует ли это считатьld.bfd ошибка илиld.gold ошибка.libstdc++Почему я должен упомянуть оба -pthread и -lpthread оба? (-pthread передается по умолчанию нашей системой сборки, и я использую -lpthread, чтобы он работал с золотом).

 а также

-pthread делать разные вещи (см.-lpthreadpthread против lpthread). Насколько я понимаю, первое должно подразумевать второе.Несмотря на это, вы, вероятно, можете пройти

 только один раз, но вам нужно сделать это-lpthreadдоили используйте --as-needed после последней библиотеки и до--no-as-neededТакже стоит упомянуть, что я не смог воспроизвести эту проблему в моей системе (GCC 7.2), даже используя золотой компоновщик. Поэтому я подозреваю, что это было исправлено в более поздней версии libstdc ++, что также может объяснить, почему он не работает по умолчанию, если вы используете системную стандартную библиотеку.-lpthread.

Является

 sbabbi16 нояб. 2017 г., 19:22
Если это значение равно 0, проверка, очевидно, удаляется. Я ожидаю, что в этом случае в результатеGTHREAD_USE_WEAK следует явно ссылаться наlibstdc++, Я собираюсь попытаться собрать libstdc ++ без этого флага и посмотреть, что произойдет.pthreadЭто, вероятно, проблема, вызванная тонким несоответствием между
 Nawaz15 нояб. 2017 г., 17:51
Параметры компиляции и компоновки к вопросу. Пожалуйста, посмотрите это[email protected] Наваз Да, он делает что-то подобное. Но есть флаг сборки для libstdc ++, который называется
 sbabbi13 нояб. 2017 г., 16:54
 Nawaz13 нояб. 2017 г., 16:13
"__gthread_once«.pthread_once... Это задокументировано[email protected]
 Nawaz13 нояб. 2017 г., 16:12
 а также__gthread_once такой же? Они кажутся разными API. Первое, кажется, определено вpthread_onceтогда как последний вlibgcc еще один встроенный символ, который всегда долженlibpthread.

Ваш ответ на вопрос