2013-07-15 48 views
2

G-WAN是一種方便的方法,可以在Web上立即運行C代碼,但對於我而言,它不適用於valgrind。 (運行valgrind ./gwan有一個錯誤信息Inconsistency detected by ld.so: rtld.c: 1292: dl_main: Assertion `_rtld_local._dl_rtld_map.l_libname' failed!然後它退出;系統是Debian Jessie 64位)。與valgrind的G-WAN?備擇方案?

問題是:
1)G-WAN是否應該與valgrind一起工作?
2)在G-WAN下運行的C代碼中是否有其他可行的方法來檢測內存錯誤?

回答

1

G-WAN是否應該與valgrind一起工作?

我們測試了Valgrind,雖然它做了很多事情,但它並不適用於高併發作業(即使低併發性是Valgrind的問題)。

可行的選項來檢測在G-WAN下運行的C代碼中的內存錯誤?

使用malloc()包裝,預分配池,或者甚至更好,使用alloca()避免在首位內存問題。

需要注意的是G-WAN處理C腳本錯誤指針沒有崩潰的服務器,請參閱:http://gwan.ch/developers#crash

此bug的代碼:

int main(int argc, char *argv[]) 
{ 
    strcpy(0xBADC0DE, 0xBADC0DE); 
    return 200; 
} 

...會產生類似下面的 '優雅'崩潰報告:

Script: crash_libc.c 
Client: 127.0.0.1 
Query : ?crash_libc 

Signal  : 11:Address not mapped to object 
Signal src : 1:SEGV_MAPERR 
errno   : 0 
Thread  : 0 
Code Pointer: 0000f5200b33 (module:/lib/libc.so.6, function:strcpy, line:0) 
Access Address: 00000badc0de 

Registers  : EAX=00000badc0de CS=00000033 EIP=0000f5200b33 EFLGS=000000010202 
       EBX=000000000001 SS=ec2d8ed4 ESP=0000f5ded828 EBP=0000f5dee020 
       ECX=000033323130 DS=ec2d8ed4 ESI=0000ec2d8f86 FS=00000033 
       EDX=000003b03c00 ES=ec2d8ed4 EDI=00000badc0de CS=00000033 

Module  :Function  :Line # PgrmCntr(EIP) RetAddress FramePtr(EBP) 
     libc.so.6:   strcpy:  - 0000f5200b33 0000ec2d8f00 0000f5dee020 
     servlet:   main: 37 0000ec2d8f00 00000042e10c 0000f5dee020   

和G-WAN竟把告訴你在哪裏錯誤在源代碼中發生(見G-WAN crash_xxx.c例子)instea d殺死服務器進程。

如果您不想調試C代碼,然後使用Java或Scala(均由G-WAN支持) - 您將需要更多內存,因爲您的數據將保持加載狀態,直到GC將所有內容放慢它認爲可以釋放 - 但至少你會享受更少的內存相關的錯誤,如果有的話。


根據提問人的要求,這裏有更多的細節。

2012年底,我們測試了十幾種免費和商業工具,像Valgrind一樣,應該幫助調試併發性。我們還使用靜態工具來學習源代碼,而不僅僅是運行(編譯)程序的動態工具。

可悲的事實是,他們都從常見問題的困擾,他們:

  • 一般都支持併發(核問題)
  • 瑣碎警報的產生gazillions(甚至更多的假警報太慢)
  • 是非常昂貴的(這是或商業的當然),並不能總是在購買前測試(!)

所以,周檢查和過濾所有這些結果後,我們花了很多時間「糾正」的G-WAN的代碼庫,以消除因無法區分工具的瑣碎和假警報(警報從錯誤的代碼中得到有效的代碼)......但是,當時我們感到沮喪,我們還沒有在G-WAN中發現任何真正的錯誤(明確表明這幾周浪費了時間)。

因此,上面的結論是:儘可能簡化代碼,並在需要更復雜的策略時嘗試預先分配塊。

當然,Linux LIBC堅持用(不可捕捉的)abort信號殺死應用程序並不能幫助(這可以防止程序從恢復或轉儲相關跟蹤),尤其是對於馬虎的雙免費Linux LIBC檢測(錯誤地認爲當程序使用malloc()一次時,所有代碼都使用它的malloc() - 這通常由LIBC調用完成!)。我甚至沒有談論mmap()失敗,也沒有談到OOM kill-switch。

到目前爲止,我們發現的唯一解決方案是避免使用Linux LIBC,並用我們自己的C運行時編譯我們需要的所有東西。對於所有用戶,這是一個難以推薦的「要做的事情」,但它對我們有效。

我們很高興看到Linux使用我們的部分代碼(或者至少一些在G-WAN中實現的概念),因爲這會使我們的生活(以及許多其他開發人員)變得非常容易,但過去我們與「負責人」進行的接觸並不令人鼓舞。總而言之,從操作系統,像我們這樣的獨立軟件開發商和開發者那裏有改進的餘地 - 畢竟,自2004年以來,併發只是「主流」......差不多十年前。

+0

Valgrind在signle核心上運行,但它調試高併發作業NP。當你有一個錯誤時,你總是可以將一部分流量重定向到一個valgrind-ed服務器。像DUMA和ElectricFence這樣的LD_PRELOAD malloc包裝器也不能與G-WAN一起工作(DUMA立即崩潰,EF在'stream3.c'中崩潰)。當處理異步代碼時,內存處理並不像alloca那麼簡單,即使使用alloca,如果可能的話,每個大型程序都會有錯誤和內存損壞。感謝您的回答。然而問題在於:什麼是G-WAN的工作valgrind選擇? – ArtemGr

+0

我會在上面的回覆中添加更多細節,但簡而言之(真正有能力的)併發調試工具目前還沒有商業可用。 – Gil

+0

再次感謝Gil的回答。不過,你對這個場景的失望並不是解決調試代碼問題的一個解決方案。在新的編譯器中,「-fsanitize = address」如何?您是否計劃在G-WAN中支持? – ArtemGr