2016-07-07 87 views
5

我希望這個問題不是太開放。我遇到了Rust的內存問題,我在那裏得到了an "out of memory" from calling next on an Iterator trait object。我不確定如何調試它。打印只會讓我發生故障。我對ltrace等其他工具並不是很熟悉,所以儘管我可以創建一個跟蹤(231MiB,pff),但我並不知道如何處理它。這樣的痕跡有用嗎?我會更好地抓住gdb/lldb嗎?還是Valgrind?如何在Rust中調試內存問題?

+0

Valgrind總是一個好的開始。嘗試優化您的代碼。 –

+2

@EliSadoff如何優化我的代碼有助於調試內存問題? – Apanatshka

回答

3

一般來說我會試着做下面的辦法:

  1. 樣板減少:儘量縮小OOM的問題,讓您不必四處太多額外的代碼。換句話說:程序崩潰越快,效果越好。有時候也可以將特定的一段代碼翻譯成一個額外的二進制代碼,僅供調查。

  2. 問題尺寸縮小:下從OOM簡單的「過多的內存」,讓你可以真正說出一些部分廢物的東西,但它不會導致OOM問題。如果很難分辨出是否存在問題,則可以降低內存限制。在Linux上,這可以使用ulimit做到:

    ulimit -Sv 500000 # that's 500MB 
    ./path/to/exe --foo 
    
  3. 信息收集:如果你的問題是足夠小,你就可以收集具有較低的噪音水平的信息。有多種方法可以嘗試。只要記住用調試符號編譯你的程序。此外,關閉優化可能是一個優勢,因爲這通常會導致信息丟失。兩者都可以通過在編譯期間不使用--release標誌進行歸檔。

    • 堆紋:一種方法是使用過gperftools

      LD_PRELOAD="/usr/lib/libtcmalloc.so" HEAPPROFILE=/tmp/profile ./path/to/exe --foo 
      pprof --gv ./path/to/exe /tmp/profile/profile.0100.heap 
      

      這說明你這象徵着你的程序的部分吃內存,並且量的曲線圖。有關更多詳細信息,請參見official docs

    • rr:有時很難找出實際發生的情況,尤其是在創建配置文件後。假設你沒有在步驟2中的好工作,你可以使用rr

      rr record ./path/to/exe --foo 
      rr replay 
      

      這將產生一個GDB與超級大國。與普通調試會話的區別在於,您不僅可以使用continue,還可以使用reverse-continue。基本上你的程序是從錄音中執行的,你可以隨意來回跳動。 This wiki page爲您提供了一些額外的例子。有一點需要指出的是,rr似乎只適用於GDB。

    • 良好的舊調試:有時你會得到痕跡和記錄仍然太大。在這種情況下,你可以(與ulimit招組合)只使用GDB,等到程序崩潰:

      gdb --args ./path/to/exe --foo 
      

      您現在應該得到正常的調試會話,你可以檢查一下程序的當前狀態爲。 GDB也可以用coredumps啓動。這種方法的一般問題是,你不能回到過去,你不能繼續執行。所以你只能看到當前狀態,包括所有的棧幀和變量。如果你願意的話,你也可以使用LLDB。

  4. (潛在的)固定+重複:後你有膠水什麼可能出錯,你可以試着改變你的代碼。然後再試一次。如果仍然無法使用,請返回步驟3並重試。

1

通常,爲了調試,您可以使用基於日誌的方法(通過自己插入日誌或使用諸如ltraceptrace等工具爲您生成日誌),也可以使用使用調試器。

請注意,ltraceptrace或基於調試器的方法要求您能夠重現問題;我傾向於支持手動日誌,因爲我在一個行業工作,那裏的bug報告通常太不精確,無法立即複製(因此我們使用日誌創建複製器場景)。

Rust支持這兩種方法,而用於C或C++程序的標準工具集適用於它。

我個人的做法是讓進行一些的日誌記錄以快速縮小發生問題的位置,並且如果日誌記錄不足以激發調試器以進行更精細的檢查。在這種情況下,我會建議直接調試器。

將生成一個panic,這意味着通過中斷對恐慌鉤子的調用,您可以在出現錯誤時看到調用堆棧和內存狀態。

用調試器啓動程序,在恐慌鉤上設置一個斷點,運行程序,獲利。