2010-08-05 123 views
7

我開發了一個使用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)。

回答

3

dyld正在共享庫中運行初始化程序(認爲C++中的靜態初始化程序),其中一個引起CoreFoundation框架的__CFInitialize函數運行。 [這可能是接觸CoreFoundation的第一件事情嗎?]無論出於何種原因,__CFInitialize都不太開心。這可能是某種缺失的依賴。或者它可能是堆已損壞。或者它可能是CoreFoundation框架中某種潛在的bug。

我會建議通過以下方法修剪前兩種可能性:a)運行所有DYLD_PRINT_ *環境變量集[參見man dyld]和b)在MallocDebug下運行。如果這兩者都沒有任何亮點,那麼您可能會留下爲CoreFoundation人員編寫雷達。

+0

真棒,謝謝。我會嘗試這兩個,看看會發生什麼。我還會回覆我找到的供將來參考。 – 2010-08-10 21:36:20

7

經過一些進一步的問題和一些進一步的谷歌搜索,我最終找到了我的問題的真正原因。

如果CoreFoundation未初始化,則不能在(子)線程中與CoreFoundation鏈接的庫調用dlopen庫。調用CFInitialize,顯然會檢查線程是否是主線程,如果不是,則使用SIGTRAP進行崩潰。

http://openradar.appspot.com/7209349