-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Description
Here is a very simple program which employs trait objects:
c.rc:
#[crate_id = "c#0.1"];
#[crate_type = "bin"];
mod m1;
mod m2;m1.rs:
use std::io;
pub struct Container<'a> {
priv reader: &'a mut Reader
}
impl<'a> Container<'a> {
pub fn wrap<'s>(reader: &'s mut Reader) -> Container<'s> {
Container { reader: reader }
}
pub fn read_to(&self, vec: &mut [u8]) {
self.reader.read(vec);
}
}
pub fn for_stdin<'a>() -> Container<'a> {
let mut r = io::stdin();
Container::wrap(&mut r as &mut Reader)
}m2.rs:
use std::vec;
use m1;
#[main]
fn main() {
let c = m1::for_stdin();
let mut v = vec::from_elem(10, 0u8);
c.read_to(v.as_mut_slice());
}When this program is compiled and run, it fails with segmentation fault:
% rustc c.rc
% ./c
zsh: segmentation fault (core dumped) ./c
This program is not correct. You can see that m1::for_stdin() function produces a Container<'a, ...> for arbitrary lifetime 'a, but the local variable r is valid only for for_stdin() body. A pointer to r, however, is saved to the Container, and when it is accessed inside m2::main(), a segmentation fault occurs. However, Rust still compiles it. I thought that borrowing checker should prevent this kind of errors.
BTW, I can write &mut r or &mut r as &mut Reader and it will compile either way, but I thought that when going from plain pointers to trait objects I should always specify exact kind of trait object. Not sure that I'm right here thought.