Я создал инструмент C ++ для рендеринга 3D-моделей за пределами экрана. Рендеринг выполняется с использованием библиотеки OSMesa.
Программное обеспечение работало безупречно больше года, и я перестал обновлять его примерно 6 месяцев назад. Между тем, моя среда разработки обновлялась несколько раз.
Теперь я снова его компилировал и обнаружил неожиданную ошибку.
Обычная версия программного обеспечения все еще работала, как и ожидалось, но статически связанная версия — это segfaulting.
Я предполагаю, что ошибка моя в процедуре конфигурирования / компиляции / компоновки OSmesa, а не в коде библиотеки, но любые советы по улучшению отладки ошибки сегментации приветствуются.
Попробовав многочисленные варианты процесса компиляции без успеха, я теперь застрял.
Кто-нибудь может увидеть что-то глупое, что я делаю в некоторых шагах, описанных ниже?
Я перекомпилировал статическую версию библиотеки OSmesa с той же версией общей библиотеки, которая работает в моей системе (12.0.6), отключив все ненужные функции (с использованием системы на основе Ubuntu, статическая версия OSmesa lib отсутствует). доступно из репозиториев):
./ настроить \ --disable-xvmc \ --disable-glx \ --disable-dri \ --with-dri-drivers = "" \ --with-gallium-drivers = "" \ --disable-shared-glapi \ --disable-egl \ --with-egl-platform = "" \ --enable-osmesa \ --enable-gallium-llvm = нет \ --disable-gles1 \ --disable-gles2 \ --enable-static \ --disable-общий
Это команда компиляции моего внеэкранного инструмента рендеринга:
g ++ -std = c ++ 11 -Wall -O3 -g -static -static-libgcc -static-libstdc ++ ./src/measure_model.cpp model.o thumbnail.o -o measure_model_debug -pthread -lOSMesa -ldl -lm -lpng -lz -lcrypto
Это предупреждение, которое я получал статической компиляцией с использованием OSMesa, и это было даже год назад с рабочим статическим двоичным файлом:
/home/XXX/XXX/backend/lambda/mesa/mesa-12.0.6/src/mesa/main/dlopen.h:52: предупреждение: использование «dlopen» в статически связанных приложениях требует во время выполнения общих библиотек из glibc версия, используемая для ссылки
Вот что я получаю от запуска инструмента:
Ошибка сегментации (ядро сброшено)
Но ошибка сегментации не возникает, если я просто пропущу этап создания контекста OSmesa (и, очевидно, весь 3D-рендеринг)
Это обратный след:
# 0 0x0000000000000000 in ?? () # 1 0x00000000004af20a в mtx_init (тип = 4, mtx = 0xe10f70) в ../../include/c11/threads_posix.h:215 # 2 _mesa_NewHashTable () в main / hash.c: 135 # 3 0x000000000052f295 в _mesa_alloc_shared_state (ctx = ctx @ entry = 0xdcc9b0) в main / shared.c: 67 # 4 0x000000000046e717 в _mesa_initialize_context (CTX = CTX @ запись = 0xdcc9b0, апите = апи @ запись = API_OPENGL_COMPAT, визуальный =, share_list = share_list @ запись = 0x0, driverFunctions = driverFunctions @ запись = 0x7fffffffcd40) на главном / context.c: тысяча сто девяносто-две # 5 0x000000000046c870 в OSMesaCreateContextAttribs (attribList = attribList @ entry = 0x7fffffffd290, sharelist =) в osmesa.c: 834 # 6 0x000000000046ccdc в OSMesaCreateContextExt (format =, deepBits =, stencilBits =, StorageBits =, sharelist =) в osmesa.c: 660 # 7 0x0000000000468742 в generate_thumbnail (Model *, Json :: Value) () # 8 0x0000000000401c7d в основном (argc =, argv =) в ./src/measure_model.cpp:107
Статически связанный двоичный файл является строгим требованием.
Ошибка сегментации происходит на той же машине, которую я использую для компиляции инструмента (статическая библиотека OSmesa компилируется и на той же машине), но нет ошибки сегментации в не статически связанной версии того же инструмента.
Вот что я получаю от запуска инструмента:
Segmentation fault (core dumped)
Но ошибка сегментации не возникает, если я просто пропущу этап создания контекста OSmesa (и, очевидно, весь 3D-рендеринг)
Итак, есть проблема с созданием OSmesa. С вашей обратной трассировкой мы можем видеть, что функция top была выполнена из EIP с нуля (переход к NULL / вызов NULL), поэтому есть вызов некоторой функции в mtx_init
, которая является частью создания контекста OS Mesa.
#0 0x0000000000000000 in ?? ()
#1 0x00000000004af20a in mtx_init (type=4, mtx=0xe10f70) at ../../include/c11/threads_posix.h:215
#2 _mesa_NewHashTable () at main/hash.c:135
#3 0x000000000052f295 in _mesa_alloc_shared_state (ctx=ctx@entry=0xdcc9b0) at main/shared.c:67
#4 0x000000000046e717 in _mesa_initialize_context (ctx=ctx@entry=0xdcc9b0, api=api@entry=API_OPENGL_COMPAT, visual=, share_list=share_list@entry=0x0, driverFunctions=driverFunctions@entry=0x7fffffffcd40) at main/context.c:1192
#5 0x000000000046c870 in OSMesaCreateContextAttribs (attribList=attribList@entry=0x7fffffffd290, sharelist=) at osmesa.c:834
#6 0x000000000046ccdc in OSMesaCreateContextExt (format=, depthBits=, stencilBits=, accumBits=, sharelist=) at osmesa.c:660
#7 0x0000000000468742 in generate_thumbnail(Model*, Json::Value) ()
#8 0x0000000000401c7d in main (argc=, argv=) at ./src/measure_model.cpp:107
Какая была функция? В соответствии с онлайн источники включают / c11 / threads_posix.h: mtx_init()
на GitHub, есть только звонки pthread_mutex_init
, pthread_mutexattr_init
и несколько других связанных с мьютексом функций libpthread (-lpthread
).
Почему вместо реальной функции был произведен вызов NULL? Вероятно, из-за использования статической связи glibc и / или libpthread. Точная проблема до сих пор не определена (Мне удалось найти отчет о статически связанном libpthread.a в какую-то общую библиотеку, которая неверна и никогда не будет работать).
В вашем случае есть только псевдоним (сильный) из pthread_mutex_init
в glibc / nptl / pthread_mutex_init.c (строка 150) strong_alias (__pthread_mutex_init, pthread_mutex_init)
и может быть некоторый слабый псевдоним символа в самом glibc, вероятно, неинициализированный. Некоторые были не правы в ваших ссылках или / и в ld
возражать, и он не нашел / связать nptl/pthread_mutex_init.o
(это часть архива libpthread.a) с реальным символом в конечном исполняемом файле (ld часто пропускает неиспользуемые / ненужные объекты архивов .a и не связывает их в конечный исполняемый файл), сохраняя перемещение, указывающее на NULL. Какой-то эксперт по glibc может знать, Занятый русский является одним из экспертов по SO.
Я предлагаю связывать статически только со своими внутренними библиотеками или, возможно, также с обычными несистемными библиотеками, такими как mesa (вы можете использование -Wl,-Bstatic -lyour_lib -Wl,-Bdynamic
варианты временного изменения связи со статической для библиотек, перечисленных между; или используйте чит-опцию -l:
как -l:libYour_lib.a
найден Радеком в том же д.). Но не связывайте статически с большинством базовых библиотек glibc, таких как libc, libpthread, librt (существуют некоторые проблемы статического связывания glibc, когда используется nss: целевая система должна иметь точно такую же версию динамического glibc, чтобы nss работал).
Если вы хотите упаковать свое приложение для более старых машин и вам нужны некоторые функции glibc, вы можете также попытаться упаковать свою собственную версию совместно используемых библиотек glibc с вашим приложением; поместите их в некоторый подкаталог, добавьте rpath
возможность компоновщика изменить пути поиска в библиотеке, а также изменить Раздел INTERP по умолчанию ABI ld-linux.so.2 загрузите вашу собственную копию ld-linux.so.2 из вашей версии glibc, … И у вас все еще будут проблемы со слишком старыми ядрами, поскольку для новых glibcs требуются некоторые современные функции (системные вызовы, структуры) относительно нового ядра.
Или вы можете упаковать свое приложение в какой-то контейнер, такой как Docker, или какой-то другой изоляция решение (или chroot?), чтобы всегда иметь ваши версии библиотек …
ОБНОВЛЕНИЕ: Просто найденный отчет о подобном bt с NULL вместо реализации мьютекса из nptl: https://bugzilla.redhat.com/show_bug.cgi?id=163083 «Статически связанная программа на C ++ с использованием pthreads приведет к сбою» (2005-2007) pthread_mutex_init(&lock, NULL);
g++ -g -static foo.cpp -o foo -lpthread
where #0 0x00000000 in ?? () #1 0x08048232 in main () at foo.cpp:7
По-видимому, это связано с тем, что некоторые функции pthreads не включены в исполняемый файл вывода. Эта ошибка может дублировать # 115157, и я прошу прощения, если так, но, надеюсь, включенный тестовый пример будет полезен.
Дополнительная информация:
Предложение в # 115157 принудительно ссылаться во всех файлах libpthread.a является допустимым обходным решением.
https://bugzilla.redhat.com/show_bug.cgi?id=115157 «исполняемые файлы, статически связанные с /usr/lib/nptl/libpthread.a fail» — 2004-2009 CLOSED WONTFIX
Jakub Jelinek 2004-10-29 05:26:10 ПО ВОСТОЧНОМУ ВРЕМЕНИ
Прежде всего, избегайте
-static
если вы можете, это только создает проблемы,
как с точки зрения мобильности, так и с другими.Если вам действительно нужно создать статически связанный бинарный файл с
-lpthread
связаны, то просто используйте-Wl,--whole-archive -lpthread -Wl,--no-whole-archive
вместо-pthread
. У всего остального действительно много проблем.
Других решений пока нет …