2009-07-03 45 views
0

我有一個由用C++編寫的不同模塊組成的應用程序。
其中一個模塊用於處理SunGrid Engine上的分佈式任務。它使用DRMAA API來提交和監控網格作業。如果客戶端不支持網格,應使用本地機器

API libdrmaa.so的共享對象在編譯時鏈接並在運行時加載。
如果使用我的應用程序的客戶端具有此「.so」,則一切正常,但如果客戶端沒有該應用程序, 應用程序將退出未能加載共享庫。
爲了避免這種情況,我使用dlsym()和dlopen()函數指針取代了API調用。 現在我可以使用本地機器而不是網格,如果對dlopen的調用不成功並且我的目標已實現。
現在的問題是,應用程序現在可以成功運行小型測試用例,但使用較大的測試用例時,它會引發段錯誤,而使用動態加載的相同代碼正常工作。使用C動態加載例程的問題

我在使用dlsym()和dlopen()時丟失了什麼?
有沒有其他方法可以達到同樣的目標?

任何幫助,將不勝感激。

感謝名單,

回答

3

對於通過dlsym()加載的代碼來說,這不太可能是一個直接的問題 - 在這種意義上說,動態加載會導致分段錯誤。

它可能會做的是暴露一個單獨的問題,可能是通過移動東西。這可能意味着一個在靜態鏈接情況下指向某處「合法」但在動態鏈接情況下的其他地方的一個零散(未初始化)指針,並且其他地方會觸發seg-fault。事實上,從長遠來看,這對你是有好處的 - 它表明存在一個可能長期未被發現的問題。

我認爲這很有可能,因爲你提到它發生在較大的測試中,而不是小的測試。

+0

是啊..我同意你..但我應該如何去糾正這個??整個代碼很笨重:(.. – sud03r 2009-07-03 15:49:27

0

如果要跨一個的extern拋出一個異常,「C」功能,那麼應用程序必須退出。這是因爲C ABI沒有設施來傳播異常。

爲了在使用DLL(或共享庫)時對此進行處理,您通常會有一個C函數返回一個C++對象。然後剩下的交互就是從DLL返回的那個C++對象。

此模式建議(和我強調建議)像對象的工廠,因此你的DLL應該有一個單一的extern「C」函數,返回一個void *,你可以重新編譯回一個C++工廠對象。

1

正如Jonathan Leffler所說,在您直接使用API​​的情況下,問題很可能存在;它只是還沒有導致崩潰。

你的第一步,當你得到一個SIGSEGV應分析產生的核心轉儲(或乾脆直接運行應用程序在調試器下),並期待其中墜毀。我會下注$ 0。02,它的崩潰某處內部mallocfree,在這種情況下,問題是普通的舊堆損壞,並有許多可以幫助你抓住這堆檢查工具。 Solaris提供watchmalloc,這是一個好的開始。