调试
在我们编写更多代码之前,我们需要掌握一些调试工具,以便在出现问题时使用。请花点时间查看参考页面,其中列出了用于调试 Rust 生成的 WebAssembly 的工具和方法。
启用恐慌日志
如果我们的代码出现恐慌,我们希望在开发者控制台中显示信息丰富的错误消息。
我们的 wasm-pack-template
带有一个可选的、默认启用的依赖项,即console_error_panic_hook
箱子,它在 wasm-game-of-life/src/utils.rs
中配置。我们只需要在初始化函数或通用代码路径中安装钩子。我们可以在 wasm-game-of-life/src/lib.rs
中的 Universe::new
构造函数中调用它。
# #![allow(unused_variables)] #fn main() { pub fn new() -> Universe { utils::set_panic_hook(); // ... } #}
向我们的生命游戏添加日志
让我们使用 web-sys
箱子中的 console.log
函数添加一些关于我们 Universe::tick
函数中每个单元格的日志。
首先,在 wasm-game-of-life/Cargo.toml
中添加 web-sys
作为依赖项并启用其 "console"
功能。
[dependencies.web-sys]
version = "0.3"
features = [
"console",
]
为了提高人体工程学,我们将 console.log
函数包装在一个 println!
样式的宏中。
# #![allow(unused_variables)] #fn main() { extern crate web_sys; // A macro to provide `println!(..)`-style syntax for `console.log` logging. macro_rules! log { ( $( $t:tt )* ) => { web_sys::console::log_1(&format!( $( $t )* ).into()); } } #}
现在,我们可以通过在 Rust 代码中插入对 log
的调用来开始将消息记录到控制台。例如,要记录每个单元格的状态、活邻居计数和下一个状态,我们可以像这样修改 wasm-game-of-life/src/lib.rs
diff --git a/src/lib.rs b/src/lib.rs
index f757641..a30e107 100755
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -123,6 +122,14 @@ impl Universe {
let cell = self.cells[idx];
let live_neighbors = self.live_neighbor_count(row, col);
+ log!(
+ "cell[{}, {}] is initially {:?} and has {} live neighbors",
+ row,
+ col,
+ cell,
+ live_neighbors
+ );
+
let next_cell = match (cell, live_neighbors) {
// Rule 1: Any live cell with fewer than two live neighbours
// dies, as if caused by underpopulation.
@@ -140,6 +147,8 @@ impl Universe {
(otherwise, _) => otherwise,
};
+ log!(" it becomes {:?}", next_cell);
+
next[idx] = next_cell;
}
}
使用调试器在每次滴答之间暂停
浏览器的逐步调试器对于检查 Rust 生成的 WebAssembly 与之交互的 JavaScript 很有用。
例如,我们可以使用调试器在 renderLoop
函数的每次迭代中暂停,方法是在调用 universe.tick()
之前放置一个 JavaScript debugger;
语句。
const renderLoop = () => {
debugger;
universe.tick();
drawGrid();
drawCells();
requestAnimationFrame(renderLoop);
};
这为我们提供了一个方便的检查点,用于检查记录的消息,并将当前渲染的帧与之前的帧进行比较。
练习
-
向
tick
函数添加日志,记录每个从活到死或从死到活状态转换的单元格的行和列。 -
在
Universe::new
方法中引入一个panic!()
。在 Web 浏览器的 JavaScript 调试器中检查恐慌的回溯。禁用调试符号,在没有console_error_panic_hook
可选依赖项的情况下重新构建,然后再次检查堆栈跟踪。没有那么有用,是吗?