2015-04-06 3 views
1

По сложной проблеме, без которой невозможно обойтись без небезопасных блоков, содержится в ссылках структуры на что-то, принадлежащее другому атрибуту этой структуры.Небезопасные ссылки на атрибуты одной и той же структуры

Однако небезопасных блоков, это довольно легко, можно сделать что-то вроде:

struct Foo { 
    bar: &'static str, 
    foo: String 
} 

impl Foo { 
    pub fn new(s: String) -> Foo { 
     Foo { 
      bar: unsafe { ::std::mem::transmute(&s[..]) }, 
      foo: s 
     } 
    } 
} 

Вот вопрос: не представила метод структуры Foo ранее определенной дает &mut доступ к нему (в-структуру таким образом, никогда не будет изменен после создания), зная, что данные String выделены в виде кучи, действительно ли этот код безопасен (в соответствии с значением ржавчины «безопасным»)? Если нет, то в каких ситуациях может возникнуть проблема?

ответ

2

&mut доступ нет (это) важное. Важно то, что String никогда не изменяется (по крайней мере, без изменения &'static str), другие данные могут меняться по всем, что нам нужно. Кроме того, если &mut позволит код третьей стороны, чтобы изменить строку, то они могли бы также изменить его без указателя, с помощью унаследованной изменчивости:

let x = Foo::new(string); 
let mut x = x; 
x.foo = other_string; 
println!("{}", x.bar); // 

Таким образом, в крайней мере, вы должны держать атрибут приватный и аудит всех код в том же модуле (не только impl Foo!). Там другая проблема, хотя: Если вы когда-либо Раздайте &'static str, то да, это небезопасно:

let x = Foo::new(string); 
let s: &'static str = obtain_str(x); 
drop(x); 
println!("{}", s); // use after free 

Так что вы можете смело делать с такого рода самоссылки является очень ограничено. Вторая проблема может, , возможно,, быть предотвращена с соответствующим использованием сроков службы, но это попадает в область, где я не желаю принимать безопасность без сложного полуформального аргумента.

Для случаев использования, я полагаю, вероятно, легче укусить пулю и держаться подальше от unsafe.

+0

Я вижу. Таким образом, если все поля являются частными, и единственный доступ к содержимому осуществляется с помощью метода, например 'pub fn get_str <'a> (& 'a self) -> &' a str {& self.bar}', что может пойти не так, как надо ? – Levans

+0

@ Levans Много вещей, я бы сделал ставку. Или, может быть, вообще ничего. Как я уже сказал, я не в своей глубине: я могу указать на дыры в безопасности, как я их нахожу, но не найти никого не дает мне большой уверенности. – delnan

+0

Да, это имеет смысл. – Levans

Смежные вопросы