在OSX上通过dlopen打开库时调试崩溃

问题描述:

我开发了一个使用dlopen加载用户开发的库的C++应用程序时出现问题。在过去的几年中,这个应用程序已经被各种各样的Linux发行版和OSX版本所使用,所以我假定我的dlopen用法是OK的,依赖于它的代码也是OK的(是的,这是傲慢,所以我会报告失败时)。我现在的问题是用户开发了一个不加载我的系统的库(OSX 10.6.4)。当系统尝试加载它时,会出现冻结,然后崩溃。该崩溃线程看起来像这样的崩溃报告:在OSX上通过dlopen打开库时调试崩溃

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's Ice,播放器/舞台和OpenCV(后者2手动编译并使用MacPorts安装依赖项)。看来这是包含OpenCV导致的问题,因为其他链接到OpenCV以外的所有这些库都可以毫无问题地加载。这些是我的怀疑,但我目前缺乏进一步调查的诀窍。

谢谢!尼克

UPDATE:由于凯林的回答(在DYLD_PRINT_ *这是我以前没有意识到的选项),我至少能确认什么也没有发生完全明显。使用调试信息,我能够将问题缩小到导致崩溃的特定库。事实证明,这个库(libdc1394通过libhighgui在OpenCV中链接到我的应用程序中)没有正确链接到CoreServices,这导致了崩溃。出于某种原因,这个错误被其他东西隐藏起来,导致最终的崩溃。有关libdc1394问题的信息,请看here。不幸的是,我无法做出一个我可以在这里报告的简单修复方法,因此只是设法运行一个没有链接到恶意库的应用程序版本(通过关闭OpenCV编译中的libdc1394)。

dyld正在共享库中运行初始化程序(认为C++中的静态初始化程序),其中一个引起CoreFoundation框架的__CFInitialize函数运行。 [这可能是接触CoreFoundation的第一件事情吗?]无论出于何种原因,__CFInitialize都不太开心。这可能是某种缺失的依赖。或者它可能是堆已损坏。或者它可能是CoreFoundation框架中某种潜在的bug。

我会建议通过以下方法修剪前两种可能性:a)运行所有DYLD_PRINT_ *环境变量集[参见man dyld]和b)在MallocDebug下运行。如果这两者都没有任何亮点,那么您可能会留下为CoreFoundation人员编写雷达。

+0

真棒,谢谢。我会尝试这两个,看看会发生什么。我还会回复我找到的供将来参考。 – 2010-08-10 21:36:20

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

如果CoreFoundation未初始化,则不能在(子)线程中与CoreFoundation链接的库调用dlopen库。调用CFInitialize,显然会检查线程是否是主线程,如果不是,则使用SIGTRAP进行崩溃。

http://openradar.appspot.com/7209349