繁体   English   中英

lib OSMesa离线上下文创建在C ++中失败,但仅在静态链接时才会失败

[英]lib OSMesa off-screen context creation fails in C++, but only when statically linked

我为3D模型的离屏渲染制作了一个C ++工具。 渲染是使用OSMesa库完成的。

该软件在一年多的时间里完美运行,我停下来对它进行更新,就像6个月前一样。 与此同时,我的开发环境已多次更新。

现在我再次编译它,发现了一个意外的错误。

软件的普通版本仍然按预期工作,但静态链接的版本是segfaulting。

我假设错误在OSmesa配置/编译/链接过程中是我的,而不是在库代码中,但是有关更好地调试分段错误的任何建议都是值得赞赏的。

尝试了很多编译过程的变化而没有成功,我现在很困惑。 任何人都可以看到我在下面描述的一些步骤中做的蠢事?


我重新编译了OSmesa库的静态版本,其中包含在我的系统(12.0.6)中使用的相同版本的共享库,禁用所有不需要的功能(使用基于Ubuntu的系统,没有静态版本的OSmesa lib是可从存储库获得):

./configure \
    --disable-xvmc \
    --disable-glx \
    --disable-dri \
    --with-dri-drivers="" \
    --with-gallium-drivers="" \
    --disable-shared-glapi \
    --disable-egl \
    --with-egl-platforms="" \
    --enable-osmesa \
    --enable-gallium-llvm=no \
    --disable-gles1 \
    --disable-gles2 \
    --enable-static \
    --disable-shared

这是我的屏幕外渲染工具的编译命令:

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: warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

这是我从运行该工具获得的:

Segmentation fault (core dumped)

但是,如果我只是跳过OSmesa上下文创建步骤(显然所有的3D渲染),就不会产生分段错误

这是回溯:

#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

静态链接二进制是严格的要求。

分段错误发生在我用来编译工具的同一台机器上(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

功能是什么? 根据github上的include / c11 / threads_posix.h: mtx_init()在线资源,只有pthread_mutex_initpthread_mutexattr_init和libpthread( -lpthread )的其他几个与互斥体相关的函数的调用。

为什么会产生调用NULL而不是实际函数? 可能是由于使用了glibc和/或libpthread的静态链接。 目前仍然无法识别确切的问题 (我能够找到静态链接libpthread.a的报告到一些共享的lib,这是不正确的,永远不会工作)。

在你的情况下,glibc / nptl / pthread_mutex_init.c(第150行) strong_alias (__pthread_mutex_init, 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选项临时更改链接到静态列表之间列出的库;或者使用由Radek在同一个q中找到-l: as -l:libYour_lib.a作弊选项。)。 但是不要静态链接到glibc的大多数基本库,如libc,libpthread,librt(当使用nss时,glibc的静态链接存在一些问题:目标系统必须具有完全相同的动态glibc版本才能使nss工作)。

如果您想要为旧机器打包应用程序并且需要glibc的一些功能,您也可以尝试将自己版本的共享glibc库与您的应用程序一起打包; 将它们放到某个子目录中,添加链接器的rpath选项以更改库搜索路径,也将INTERP部分从默认的ABI ld-linux.so.2加载器更改为您自己的glibc版本的ld-linux.so.2副本, ...你仍然会遇到太旧内核的问题,因为较新的glibcs​​需要一些相当新内核的现代功能(系统调用,结构)。

或者你可以将你的应用程序打包到某种容器,如Docker,或其他一些隔离解决方案(或chroot?),以便始终拥有你的libs版本......

更新:刚刚发现类似bt的报告,而不是来自nptl的mutex实现: https ://bugzilla.redhat.com/show_bug.cgi id = 163083“使用pthreads的静态链接C ++程序将会出现段错误”(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 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静态链接的可执行文件失败” - 2004-2009 CLOSED WONTFIX

Jakub Jelinek 2004-10-29 05:26:10 EDT

首先,如果可以的话,尽量避免-static ,它只会产生问题 ,包括便携性和其他问题

如果你真的需要创建静态链接二进制文件并链接-lpthread ,那么只需使用-Wl,--whole-archive -lpthread -Wl,--no-whole-archive而不是-pthread 还有其他任何问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM