2010-11-09 75 views
0

我目前遇到了使用以下配置實現以下方案的問題:GCC 3.4,Linux。中斷C函數執行並返回到C++調用者

我已經寫了一個加載共享庫(用C編寫)的工具(用C++)。這個庫有一個我無法修復的bug。問題是它讀取一些輸入並寫入解碼輸出。有時候如果輸入錯誤,這個庫沒有做任何檢查就開始解碼下面的內存區域。這會導致段錯誤。

最初我的想法是將輸入放入分頁內存(linux mmap-syscall)並保護(mprotect)最後一頁,以防止訪問。通過安裝自己的SIGSEGV處理程序,我的C++應用程序可以拋出一個異常(當編譯時使用GCC標誌-fnon-call-exceptions)。這個異常會中斷C庫的讀取。我知道這個庫不會分配任何內存(或其他資源),這可能在堆棧展開期間丟失。整個場景在我的單元測試中運行良好,其中所有內容都是單個C++應用程序。但是現在當來自lib的C代碼被調用時,我的應用程序終止了......我是否需要用-fnon-call-exceptions標誌重建這個C-SO?我無法編譯這個庫,但只能重新鏈接它,因爲我只能訪問obj文件。

這裏是執行環境的圖片:

+------------C++ APP----------+ 
|        | 
| Install SIGSEGV handler  | 
| code calling C SO functions | 
|        | 
| +----------C SO Functions------------+ 
| | execute producing SIGSEGV  | 
| +------------------------------------+ 
|        | 
| SIGSEGV Handler called  | 
| => throw Exception  | 
|  to stop execution of | 
|  C function    | 
+-----------------------------+ 

其他建議都歡迎。

非常感謝,

Ovanes


附:我看到一些建議和評論,但他們都不是一個選擇。這是爲什麼:我只有一個接口,我可以鏈接到庫。該庫用於解碼數據結構。問題是,如果我有一個長度爲-1的數組,庫開始解碼長度爲0xffffff的數組(在32位系統上)。在我看來,等待直到lib崩潰在一個單獨的過程中不是一種選擇。首先解碼一方面會佔用大量時間,另一方面會產生大量垃圾。由於我的工具需要向用戶可靠地顯示解碼輸出。他們仍然需要能夠了解痕跡。

我沒有看到這裏要解決SIGSEGV問題。首先,庫讀取數據並將其寫入我之前通過的文件句柄。我可以配置如何寫入該句柄(緩衝與否)。此外,我確切地知道它不會分配任何堆數據或資源。最後,它會嘗試訪問我的應用程序保護的內存以避免出現此類錯誤。從用戶的角度來看,我無法告訴別人:對不起,二進制跟蹤只能解碼一半,因爲有些數據不一致。我知道這些數據不一致,我完全知道如何處理這種不一致。所以我可以優雅地恢復。我想我會嘗試使用sigsetjmp/siglongjmp POSIX函數,並希望它們會更好地作爲例外。實際上,setjmp/longjmp或sigsetjmp/siglongjmp用於實現異常。

是的,我調試了我的應用程序,並看到調用堆棧是有效的。

+2

任何機會,你可以用叉子叉庫,使用不同的庫,或寫自己的圖書館嗎?試圖解決一個SIGSEGV,導致錯誤聽起來像一個傻瓜的差事,我... – 2010-11-09 18:31:54

+0

的setjmp/longjmp的 - 我忘了這些,但他們可能工作:)不過,我不太讓你對一個單獨的進程參數:你的方法也必須打電話給圖書館,等待它完成或崩潰。我有一種感覺,應用程序的目的有其他約束,但它不是很清楚它們是什麼。 – Lars 2010-11-10 17:00:44

+0

@Lars:你可能是對的。但是我仍然需要在單獨的進程中實現內存保護等,以避免產生太多的輸出。這裏的問題是,等待進程崩潰產生大約200.000,00個輸出的單個消息。整個處理將變得怪異。我需要傳遞一個文件名到附加解碼輸出的文件名並等待它完成/崩潰。比等待應用程序在崩潰的情況下需要打開文件,並在那裏寫入發生錯誤的行,關閉它,再次啓動解碼部分並將文件名傳遞給它。太複雜了 – ovanes 2010-11-10 18:21:09

回答

0

玉傢伙,

我sigsetjmp/siglongjmp做到了。奇蹟般有效。我可以將函數跳轉到調用函數的堆棧中,並在那裏進行錯誤處理。

感謝您的所有建議。

最好的問候,

Ovanes

1

不幸的是,我沒有如上所述的問題的答案 - 你是否嘗試在調試器下運行你的應用程序,看看它到底在哪裏終止?

但是,我想到的另一種方法是將故障庫的使用放入一個單獨的程序中,從您的應用程序啓動它並通過管道將數據傳遞給它。

+0

我喜歡這種替代方法的聲音。我*認爲OP在猜測他們的C共享對象需要用'-fnon-call-exceptions'重新編譯是正確的,他們不能這樣做。 – zwol 2010-11-09 18:54:20

0

這可能是愚蠢的問題,而是要考察的核心文件?或者在調試器中運行你的應用程序?

+0

@ovanes好的,這對我來說是新的。 – 2010-11-10 10:15:06