我们想要哪种断点?
这会很棒,如果能将某种形式的"断点"操作稳定下来。目前候选的公共 API 是 core::arch::breakpoint。跟踪问题: https://GitHub.com/Rust-lang/Rust/issues/133724。 然而,接近稳定的讨论表明,不同的人对"断点"的含义有着微妙但决定性的不同看法。 - 有一种"默认中止"的断点,有时也称为我们讨论中的 yeet1。这种断点可用于 mylib::assert! 类型的宏。从可靠性推理的角度来看,它等同于 abort_immediate,但从编译的角度来看,它尽可能生成代码,使附加的调试器(如果有的话)停止执行,以便用户检查状态,并且它使得在调试器中,用户可以(自行承担风险)选择继续执行超出断点。 - 还有一种"可能继续"的断点,有时也称为我们讨论中的 yeet2。从可靠性推理的角度来看,它等同于"非确定性地中止执行或继续执行",但从编译的角度来看,它尽可能生成代码,使附加的调试器(如果有的话)停止执行,并让调试器的用户有机会检查当前状态。在调试器中,用户继续执行此断点总是安全的。 这些在 这个伟大的总结 中被称为 yeet1 和 yeet2。在大多数目标上,编译器会对它们做完全相同的事情,区别仅在于在继续从断点后出现 UB 时,谁应当负责: default-abort/yeet1 表示继续是不安全的,并发生在控制调试器的人的风险上; may-continue/yeet2 表示继续是安全的,编写代码的程序员负责确保后续代码不会导致 UB。因此,Miri 的默认行为在 yeet1 和 yeet2 中会有所不同。 要强调的是,yeet2 仍然是一种优化障碍。在断点后可能出现的 UB 不允许时间旅行到断点之前,无论断点语义如何。(这源于 yeet2 可能会中止程序。)这使得将断点插入程序中成为调试 UB 的可行工具,在两种语义下都是如此。 编译器大部分时间对它们的处理相同会使得讨论两者之间的区别变得困难。在我看来,我们找到的最佳试金石是 mylib::assert! 测试:您是否认为使用 breakpoint 代替 abort/panic! 的 assert! 实现是正确的? yeet2 表示"显然不是",yeet1 表示"显然是"。我们操作的 当前文档 表示可以代替 abort 使用 breakpoint ("在没有调试工具参与的正常执行中
内容来源: rust-lang/rust