-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Closed
Description
A segmentation fault happens when using as_ref on a raw function pointer.
This code does not behave as expected:
fn foo() {
println!("Hello, World!");
}
fn main() {
unsafe {
let f = (foo as *const fn()).as_ref().unwrap();
f();
}
}This results in:
bruno@debian:~/Documents/rust$ rustc -o test test.rs
bruno@debian:~/Documents/rust$ ./test
Segmentation fault
bruno@debian:~/Documents/rust$ rust-gdb ./test
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test...done.
(gdb) run
Starting program: /home/bruno/Documents/rust/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x000055555555b27c in test::main::h0eddcc39ebf1578f ()
(gdb) bt
#0 0x000055555555b27c in test::main::h0eddcc39ebf1578f ()
#1 0x000055555555b0b3 in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hc46a3cd2285c1402 ()
#2 0x00005555555664e8 in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::ha09bfb8724951432 () at libstd/rt.rs:59
#3 std::panicking::try::do_call::h976c8164fad81bcc () at libstd/panicking.rs:479
#4 0x000055555557093f in __rust_maybe_catch_panic () at libpanic_unwind/lib.rs:102
#5 0x000055555555b700 in std::panicking::try::h1db13937c8e2cbb4 () at libstd/panicking.rs:458
#6 std::panic::catch_unwind::h3c1f03b328c42bbe () at libstd/panic.rs:358
#7 std::rt::lang_start_internal::h090df5551a0da347 () at libstd/rt.rs:58
#8 0x000055555555b097 in std::rt::lang_start::h771801e75e92adce ()
#9 0x000055555555b2ae in main ()
(gdb)
The code above would be necessary because the code below does not compile:
fn foo() {
println!("Hello, World!");
}
fn main() {
unsafe {
let f = (&foo as *const fn()).as_ref().unwrap();
f();
}
}It results in:
error[E0606]: casting `&fn() {foo}` as `*const fn()` is invalid
--> test.rs:7:17
|
7 | let f = (&foo as *const fn()).as_ref().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
The solution is to use something like:
fn foo() {
println!("Hello, World!");
}
fn main() {
unsafe {
let f = (&(foo as *const fn()) as *const *const fn() as *const fn()).as_ref().unwrap();
f();
}
}This works fine.
Rust version:
rustc 1.25.0-nightly (da569fa9d 2018-01-16)
binary: rustc
commit-hash: da569fa9ddf8369a9809184d43c600dc06bd4b4d
commit-date: 2018-01-16
host: x86_64-unknown-linux-gnu
release: 1.25.0-nightly
LLVM version: 4.0
Metadata
Metadata
Assignees
Labels
No labels