從堆裏找回「丟失」的代碼

前言

前一陣子,使用小烏龜(TortoiseGit)提交代碼的時候,錯誤的 Revert 了部分代碼,本文記錄了找回這部分代碼的過程。文章標題致敬張銀奎老師《格蠹彙編》的第一章 —— 從堆裏搶救丟失的博客。git

說明: 本文的截圖都是我用新建的示例工程截取的。windows

緣起

最近,程序運行的時候,執行某個功能會崩潰,根據經驗猜想,應該是序列化,反序列化的問題。因爲手裏沒有關鍵的 pdb,調試起來比較費勁,並且項目比較急,暫時先不使用這個功能。準備先提交其它功能的代碼。瀏覽器

大意失荊州

按照慣例,提交以前先檢查一下提交內容。(p.s. 這是個好習慣)debug

後截的圖

發現有一部分代碼會致使序列化有問題。一激動(當時被那個崩潰問題搞得很煩躁),點擊了Revert...3d

revert-source

點完了就後悔了 —— 這段代碼是爲其它功能寫的,應該保留。因爲在提交代碼前,關閉了vs ,沒辦法經過 vs 找回了。 調試

說明:若是文件在 vs 外部被修改,vs 會給出相似下圖的提示,這時候咱們選 No 不從新加載就能夠了。日誌

reload-modified-file

這但是我辛辛苦苦,一行一行敲出來的啊。就這麼 「丟了」 嗎?丟是不可能丟的,這輩子都不可能丟的。code

峯迴路轉

幸好沒有煩躁到直接幹掉小烏龜。想起張老師的《格蠹彙編》第一章就是 「從堆裏搶救丟失的博客」,講的是使用 windbg 從瀏覽器中找回未能成功發表的博文的故事。趕忙使用 windbg 附加到小烏龜上。先用 .dump /ma e:\dumps\tortoisegit.dmp 保存一份完整轉儲。cdn

保存完整轉儲

有了轉儲文件,即便關閉小烏龜也不怕了!稍微平復下我跌宕起伏的心裏,應該用哪一個命令搜索內存呢?很早以前從張老師的文章裏瞭解到 s 命令能夠搜索內存。加之,前一段日誌恰好嘗試解決過相似的問題,作了筆記。很快就把上次整理好的命令粘貼到 windbg 中進行查找。blog

搜尋關鍵字

有印象的關鍵字是 args.Contains("--all")。在 windbg 中輸入 !address -f:heap,PAGE_READWRITE -c:"s -u %1 %2 args.Contains(\"--all\")"

搜尋關鍵字

搜到兩處,分別使用 du 命令查看這兩處的內容。

查看第一個地址

查看第二個地址

明顯第一處的內容比較全,選用第一處的地址進行進一步的搜索。若是能找到文件的開始和結束就最好了。通過簡單的嘗試,找到了開始和結束的地址。截圖的話會比較長,這裏就不截圖了。開始地址是 0000022f``dae8e5f8-0x3538,結束地址是 0000022f``dae8f030

說明: 也能夠直接使用命令 s -u 0x0 L?0xffffffff`ffffffff 「args.Contains("–all")」,更簡單明瞭。

保存到文件

知道開始地址和結束地址了,剩下的就是如何把對應的內容保存到文件中了。windbg 已經爲咱們準備好了一條命令 —— .writemem。輸入:.writemem e:\dumps\tortoisegit.cs 0000022f``dae8e5f8-0x3538 0000022f``dae8f030 便可把指定範圍的數據保存到文件中。

保存到文件

查看保存的文件,果真是對應的文件內容!比較長,這裏就不放截圖了。

反思

  • 必定要養成一個良好的版本管理習慣。開發新功能的時候,最好創建一個新分支,而且隨時把變動提交。等開發完了,再合併回主分支,並刪掉功能分支。若是我遵循了這個原則的話,就不會出現這種問題了。固然,也不會有本篇總結了。

  • 遇到問題,必定不要魯莽,保持冷靜。若是我關了小烏龜,那麼丟失的代碼就真的沒辦法找回來了。

  • 必定要養成總結問題,記錄問題的好習慣!以前,有同事也遇到了相似的問題,代碼不當心弄丟了。不幸的是,沒能經過這種辦法找回來。幸運的是,當時調查的結果都有記錄,因此此次查這個問題的時候,翻出筆記。複製粘貼,回車,搞定!一鼓作氣,至關舒爽!

總結

  • 使用 !address -f:heap, PAGE_READWRITE -c:"s -u %1 %2 \"unicode_string_to_search\"" 能夠在堆上搜索 unicode_string_to_search

  • 能夠使用更簡單的 s -u start_address end_address 或者 s -u start_address L?length 搜索。

  • 使用 .writemem 能夠把指定範圍的數據保存到文件中。

參考資料

相關文章
相關標籤/搜索