偵錯 Rust 生成的 WebAssembly
本節包含 Rust 生成的 WebAssembly 偵錯秘訣。
用偵錯符號建置
⚡ 在進行除錯時,務必先用偵錯符號建置!
如果您未啟用偵錯符號,則已編譯的 .wasm
binary 檔中將不會出現 "name"
自訂區段,堆疊追蹤將會顯示像 wasm-function[42]
等的函式名稱,而不是函式的 Rust 名稱,例如 wasm_game_of_life::Universe::live_neighbor_count
。
在使用「偵錯」建置 (又稱 wasm-pack build --debug
或 cargo build
) 時,會預設啟用偵錯符號。
在「版本」建置中不會預設啟用偵錯符號。若要啟用偵錯符號,請確保在 Cargo.toml
的 [profile.release]
區段中將 debug = true
。
[profile.release]
debug = true
使用 console
API 進行記錄
記錄是我們進行假設驗證和反證,以找出程式錯誤原因的有效工具之一。在網路上,console.log
函式是將訊息記錄到瀏覽器開發者工具主控台的方式。
我們可以使用 web-sys
封裝 來取得對 console
紀錄功能的存取
# #![allow(unused_variables)] #fn main() { extern crate web_sys; web_sys::console::log_1(&"Hello, world!".into()); #}
另外, console.error
函式 具有與 console.log
相同的簽章,但開發人員工具會傾向於在使用 console.error
時捕捉和顯示堆疊追蹤以及已記錄的訊息。
參考文獻
- 使用
web-sys
封裝的console.log
- 使用
web-sys
封裝的console.error
- MDN 上的
console
物件 - Firefox 開發人員工具 — 網頁主控台
- Microsoft Edge 開發人員工具 — 主控台
- 開始使用 Chrome DevTools 主控台
記錄驚恐
console_error_panic_hook
封裝會透過 console.error
記錄意外的驚恐至開發人員主控台。這會提供 Rust 格式化的驚恐訊息,而不是取得難以除錯,又難以解讀的 RuntimeError: unreachable executed
錯誤訊息。
你只需要在初始化函式或共用程式碼路徑中呼叫 console_error_panic_hook::set_once()
來安裝掛鉤
# #![allow(unused_variables)] #fn main() { #[wasm_bindgen] pub fn init_panic_hook() { console_error_panic_hook::set_once(); } #}
使用除錯器
不幸的是,WebAssembly 的除錯說明仍並不成熟。在大部分 Unix 系統上,DWARF 用於編碼除錯器提供執行中程式碼原始碼層級檢查所需的資訊。有一個替用格式會在 Windows 上編碼類似的資訊。目前,並沒有 WebAssembly 的等效格式。因此,除錯器目前提供有限的效用,而且最後我們會逐步執行編譯器所產生的原始 WebAssembly 指令,而不是我們編寫的 Rust 原始碼文字。
W3C WebAssembly 小組有一個 關於除錯的子憲章,所以預期這項說明會在未來改進!
儘管如此,除錯器對於檢查與 WebAssembly 互動的 JavaScript,以及檢查原始 wasm 狀態仍然很有用。
參考文獻
避免一開始就除錯 WebAssembly
如果錯誤是 JavaScript 或網路 API 互動所專屬,那麼 使用 wasm-bindgen-test
撰寫測試。
如果錯誤不會涉及 JavaScript 或 Web API 的互動,那麼請嘗試以一般的 Rust #[test]
函數複製這個錯誤,在偵錯時你可以利用作業系統成熟的原生工具。使用像 quickcheck
這種測試函式庫,以及它的測試案例收縮器,來機械化地縮減測試案例。如果你能夠將錯誤孤立在較小的測試案例中,並且不需要與 JavaScript 互動,你將可以更快找到並修正錯誤。
請注意,為了在沒有編譯器和連結器錯誤情況下執行原生 #[test]
,你需要確保 "rlib"
已包含在 Cargo.toml
檔案中的 [lib.crate-type]
陣列中。
[lib]
crate-type ["cdylib", "rlib"]