在OSX上使用dlopen打开库时出现崩溃的调试

7
我开发的C++应用程序有问题,它使用dlopen加载用户开发的库。在过去几年中,该应用程序已被各种人在各种Linux发行版和OSX版本上使用,因此我认为我的dlopen使用正确,并且依赖于它的代码也是正确的(是的,这是傲慢,所以当它失败时我会回报)。现在我遇到的问题是,一个用户开发的库无法在我的系统(OSX 10.6.4)上加载。当系统尝试加载它时,会出现冻结然后崩溃。在崩溃报告中,崩溃的线程如下:
Thread 5 Crashed:
0   com.apple.CoreFoundation        0x00007fff80fa6110 __CFInitialize + 1808
1   dyld                            0x00007fff5fc0d5ce ImageLoaderMachO::doImageInit(ImageLoader::LinkContext const&) + 138
2   dyld                            0x00007fff5fc0d607 ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 27
3   dyld                            0x00007fff5fc0bcec ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 236
4   dyld                            0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157
5   dyld                            0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157
6   dyld                            0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157
7   dyld                            0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157
8   dyld                            0x00007fff5fc0bc9d ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 157
9   dyld                            0x00007fff5fc0bda6 ImageLoader::runInitializers(ImageLoader::LinkContext const&) + 58
10  dyld                            0x00007fff5fc08fbb dlopen + 573
11  libSystem.B.dylib               0x00007fff816492c0 dlopen + 61
12  cast-server-c++                 0x0000000100007819 cast::loadLibrary(std::string const&) + 96 (ComponentCreator.cpp:43)
13  cast-server-c++                 0x00000001000079c7 cast::createComponentCreator(std::string const&) + 24 (ComponentCreator.cpp:87)
14  cast-server-c++                 0x00000001000089c5 cast::CASTComponentFactory::createBase(std::string const&, std::string const&, Ice::Current const&) + 197 (CASTComponentFactory.cpp:27)
15  cast-server-c++                 0x00000001000090e9 cast::CASTComponentFactory::newManagedComponent(std::string const&, std::string const&, bool, Ice::Current const&) + 73 (CASTComponentFactory.cpp:62)
16  libCDL.dylib                    0x00000001009ceb6c cast::interfaces::ComponentFactory::___newManagedComponent(IceInternal::Incoming&, Ice::Current const&) + 218 (CDL.cpp:14904)
17  libCDL.dylib                    0x00000001009cf1d0 cast::interfaces::ComponentFactory::__dispatch(IceInternal::Incoming&, Ice::Current const&) + 572 (CDL.cpp:15057)
18  libIce.3.3.1.dylib              0x00000001000c9078 IceInternal::Incoming::invoke(IceInternal::Handle<IceInternal::ServantManager> const&) + 2004 (Incoming.cpp:484)
19  libIce.3.3.1.dylib              0x0000000100091a5d Ice::ConnectionI::invokeAll(IceInternal::BasicStream&, int, int, unsigned char, IceInternal::Handle<IceInternal::ServantManager> const&, IceInternal::Handle<Ice::ObjectAdapter> const&) + 367 (ConnectionI.cpp:2436)
20  libIce.3.3.1.dylib              0x000000010009bb40 Ice::ConnectionI::message(IceInternal::BasicStream&, IceInternal::Handle<IceInternal::ThreadPool> const&) + 416 (ConnectionI.cpp:1105)
21  libIce.3.3.1.dylib              0x00000001001a9bbc IceInternal::ThreadPool::run() + 3470 (ThreadPool.cpp:523)
22  libIce.3.3.1.dylib              0x00000001001aa4ec IceInternal::ThreadPool::EventHandlerThread::run() + 152 (ThreadPool.cpp:782)
23  libIceUtil.3.3.1.dylib          0x00000001006eb1e9 startHook + 128 (Thread.cpp:375)
24  libSystem.B.dylib               0x00007fff8167c456 _pthread_start + 331
25  libSystem.B.dylib               0x00007fff8167c309 thread_start + 13

如果需要,我可以发布完整日志,但如果将其包含在我的帖子中,它将超出正文文本限制。

在运行可执行文件的终端中,崩溃除了通知脚本捕获了一个信号外,没有任何输出。

我的问题是如何获取有关可能导致此崩溃的更多信息?如果有人能够提供可能的解决方案,我也很高兴,但首先我至少想知道在系统崩溃时如何生成有关实际错误的更多信息。

如果我在由dlopen最初打开的库上运行otool,一切看起来都很好(没有丢失的链接、符号等)。我主要怀疑的是被加载的库链接的这些特定组合以某种方式引起了此崩溃。这些其他库可以被加载,它们使用这些链接库的不同子集。记录下来,这些库包括X11、ZeroC的Ice、Player/Stage和OpenCV(后两个使用MacPorts手动编译并安装依赖项)。似乎是包含OpenCV引起了问题,因为其他连接到所有这些库,除了OpenCV的库可以无问题地加载。这是我的怀疑,但我目前缺乏进一步调查的专业知识。

谢谢!Nick

更新: 感谢Kaelin的回答(我之前不知道的DYLD_PRINT_*选项),我至少能够确认没有发生完全明显的事情。使用调试信息,我能够将问题缩小到一个特定的库,这个库导致了崩溃。结果证明,这个库(通过OpenCV中的libhighgui链接到我的应用程序中的libdc1394)没有正确地链接到CoreServices,这导致了崩溃。由于某些原因,错误被其他东西隐藏了,最终导致了崩溃。有关libdc1394问题的信息,请查看此处。不幸的是,我无法进行干净的修复,因此只能得到一个不链接到有问题的库的应用程序版本(通过在OpenCV编译中关闭libdc1394)。
2个回答

7

经过一些问题和谷歌搜索,我最终找到了我的问题的真正原因。

如果在第一次初始化CoreFoundation之前,在(子)线程中调用链接有CoreFoundation的库的dlopen是不允许的。显然,CFInitialize会被调用并检查线程是否为主线程,如果不是,则会崩溃并出现SIGTRAP。

http://openradar.appspot.com/7209349


3
dyld正在运行共享库的初始化程序(类似于C++中的静态初始化程序),其中之一导致CoreFoundation框架的__CFInitialize函数被运行。[这可能是第一次接触CoreFoundation吗?] 但由于某种原因,__CFInitialize并不顺利。这可能是某些依赖项缺失,也可能是堆已损坏,或者是CoreFoundation框架中的某种潜在错误。
我建议通过a)设置所有DYLD_PRINT_*环境变量 [请参阅man dyld]和b)在MallocDebug下运行来削减前两种可能性。如果这两个方法都没有提供任何线索,您可能需要为CoreFoundation专家编写一个radar来查看。

太棒了,谢谢。我会尝试这两个并看看会发生什么。我也会回帖分享我发现的内容,以供日后参考。 - Nick Hawes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接