use libc::kill;
use std::process;
fn main() {
unsafe {
// First SIGSEGV will be consumed by Rust runtime
// (see https://users.rust-lang.org/t/is-sigsegv-handled-by-rust-runtime/45680)...
kill(process::id() as i32, libc::SIGSEGV);
// ...but the second will crash the program, as expected
kill(process::id() as i32, libc::SIGSEGV);
}
}
use std::io::Write;
use std::io::Seek;
fn main() {
let x = 42;
let y = &x;
// Delete the next few lines and everything is good.
let mut f = std::fs::OpenOptions::new()
.write(true)
.open("/proc/self/mem").expect("welp");
// Turn y into a nullptr
f.seek(std::io::SeekFrom::Start(&y as *const _ as u64)).expect("oof");
f.write(&0usize.to_ne_bytes()).expect("darn");
println!("{y}");
}
Playground 虽然这有一些duuuuh因素,但一般技术有made some waves。甚至有人考虑这是否是一个不健全的,但最终大多被否决。(理由是Rust不能防止机器的怪异,无论是bitflips还是操作系统扰乱进程内存。 另一个不安全的SIGSEGV是堆栈溢出,正如@guest_703所提到的(但没有解释)。另一个例子:
6条答案
按热度按时间d5vmydt91#
如果允许
unsafe
代码,则:结果:
如在playground上所见。
任何会触发segfault的情况都需要在某个点调用未定义的行为。编译器被允许优化代码或利用未定义行为永远不会发生的事实,所以很难保证某些代码会segfault。编译器完全有权在不触发segfault的情况下运行上述程序。
作为示例,以上代码在 release 模式下编译时反而导致“非法指令”。
如果不允许使用
unsafe
代码,请参阅How does Rust guarantee memory safety and prevent segfaults?,了解Rust如何保证只要不违反其内存安全不变量(这只可能发生在unsafe
代码中),就不会发生这种情况。不要使用不安全的代码,如果你能避免它。
pcrecxhr2#
严格地说,总是可以欺骗程序认为它有分段错误,因为这是操作系统发送的信号:
Playground
这并不是你的问题的真正答案,因为这不是一个“真正的”分段错误,但从字面上看问题- Rust程序仍然可以以“分段错误”错误结束,这里有一个可靠触发它的案例。
eit6fx6z3#
如果你正在寻找一个更普遍的东西,将转储核心,而不是专门导致segfault,还有另一个选项,那就是导致编译器发出
UD2
指令或等效指令。有几个因素可以产生这种现象:Playground。
这不再产生UB。
!
) type。Playground。
Playground。
Playground
或使用
llvm_asm!
而不是asm!
Playground。
ne5o7dgx4#
在safe Rust中,您可以通过OS设施故意搞乱您自己进程的内存。
Playground
虽然这有一些duuuuh因素,但一般技术有made some waves。甚至有人考虑这是否是一个不健全的,但最终大多被否决。(理由是Rust不能防止机器的怪异,无论是bitflips还是操作系统扰乱进程内存。
另一个不安全的SIGSEGV是堆栈溢出,正如@guest_703所提到的(但没有解释)。另一个例子:
Playground
注意
stacker
crate可用于避免堆栈溢出。bqujaahr5#
NULL指针在C和Rust中都可能导致segfault。
jaql4c8m6#
fn main() { let arr = [5; 1000000000] }