Closed
Description
Demonstration
I uploaded a repo with the simplest possible case I could come up with that demonstrates this issue here. Here's how it works:
$ rustc --version --verbose
rustc 1.4.0-dev (d2e13e822 2015-09-15)
binary: rustc
commit-hash: d2e13e822a73e0ea46ae9e21afdd3155fc997f6d
commit-date: 2015-09-15
host: x86_64-apple-darwin
release: 1.4.0-dev
$ git clone https://github.com/kylewlacy/rust-segfault.git
$ cd rust-segfault
$ cargo build --release --verbose
Compiling my_crate v0.1.0 (file:///Users/kyle/Desktop/rust-segfault)
Running `rustc my_crate/src/lib.rs --crate-name my_crate --crate-type lib -C opt-level=3 -C metadata=ab97f46dd8433ebe -C extra-filename=-ab97f46dd8433ebe --out-dir /Users/kyle/Desktop/rust-segfault/target/release/deps --emit=dep-info,link -L dependency=/Users/kyle/Desktop/rust-segfault/target/release/deps -L dependency=/Users/kyle/Desktop/rust-segfault/target/release/deps`
Compiling segfault v0.1.0 (file:///Users/kyle/Desktop/rust-segfault)
Running `rustc src/lib.rs --crate-name segfault --crate-type lib -C opt-level=3 --out-dir /Users/kyle/Desktop/rust-segfault/target/release --emit=dep-info,link -L dependency=/Users/kyle/Desktop/rust-segfault/target/release -L dependency=/Users/kyle/Desktop/rust-segfault/target/release/deps --extern my_crate=/Users/kyle/Desktop/rust-segfault/target/release/deps/libmy_crate-ab97f46dd8433ebe.rlib`
Could not compile `segfault`.
Caused by:
Process didn't exit successfully: `rustc src/lib.rs --crate-name segfault --crate-type lib -C opt-level=3 --out-dir /Users/kyle/Desktop/rust-segfault/target/release --emit=dep-info,link -L dependency=/Users/kyle/Desktop/rust-segfault/target/release -L dependency=/Users/kyle/Desktop/rust-segfault/target/release/deps --extern my_crate=/Users/kyle/Desktop/rust-segfault/target/release/deps/libmy_crate-ab97f46dd8433ebe.rlib` (signal: 11)
Explanation
So I have a crate in my project, brilliantly named my_crate
. my_crate
is pretty simple, it contains a struct, called Foo
, made up of zero-sized types. Foo
also has a constructor function called Foo::new()
:
// my_crate/lib.rs
pub struct Foo(());
impl Foo {
fn new() -> Self {
Foo(())
}
}
Now, in my library, segfault
, I have a single function, called box_foo()
, that just returns a Box<Foo>
. It constructs a Foo
, then boxes it:
// segfault/lib.rs
extern crate my_crate;
use my_crate::Foo;
pub fn box_foo() -> Box<Foo> {
Box::new(Foo::new())
}
Well, that's about it. Building segfault
and my_crate
with cargo build
works perfectly fine. However, cargo build --release
crashes with a signal 11, a segfault.
Some observations
Foo
must be a zero-sized type, but cannot be a unit structFoo
must be constructed with a function (e.gBox::new(Foo(())
would not segfault)Foo
must be from another crate- The segfault only occurs if
box_foo()
is public (otherwise it's dead code, and I guessrustc
doesn't even attempt to compile it?) - The segfault only occurs when optimizing the outer library
- The optimization level doesn't matter, it just has to be >0
- The constructor fn doesn't have to be in
impl Foo
, but it does have to come frommy_crate
- The fn that creates the box has to be in the outer library (e.g.
let boxed: Box<Foo> = Foo::new_box();
would not segfault) - Using a newtype in place of
Foo
has the same issue - The crash is not caused by returning a
Box<Foo>
, but by constructing one withBox::new
. That is, the following also causes a segfault:
pub fn foo_ptr_mut() -> *mut Foo {
let boxed = Box::new(Foo::new());
Box::into_raw(boxed)
}