2015-03-11 20 views
5

[T; N] için IntoIterator uygulamasını deniyordum. Default ve swap (PlayPen) kullanarak tamamen güvenli bir sürüm yazdım. Daha sonra onu uninitialized, ptr::copy, Drop ve forget (PlayPen) kullanmak üzere kullandım. Benim Yineleyici yapı şöyle görünür: Ben N değeri başına bir Yineleyici yapı oluşturmak istemiyordu yana[T; U ve U her zaman [T; K]?

struct IntoIter<T> { 
    inner: Option<[T; N]>, 
    i: usize, 
} 
impl<T> Iterator for IntoIter<T> { ... } 

, ben Iterator ayarlamak zorunda

Açıkçası
struct IntoIter<U> { 
    inner: Option<U>, 
    i: usize, 
} 
impl<T> Iterator for IntoIter<[T; N]> { ... } 

için yapı değişti ve Drop uygulamaları (PlayPen). Ama şimdi bir şekilde tanımlanmamış davranışları tanıttım. Panikler println s, optimizasyon seviyelerine veya zodyak işaretlerine bağlıdır.

thread '<main>' panicked at 'index out of bounds: the len is 5 but the index is 139924442675478', <anon>:25 
thread '<main>' panicked at 'index out of bounds: the len is 5 but the index is 140451355506257', <anon>:25 
application terminated abnormally with signal 4 (Illegal instruction) 

Ya benim ikinci uygulama zaten tanımsız davranış sergileyen, veya ikinci ve üçüncü uygulamalar arasında bir fark yoktur. Oluşturulan (optimize edilmemiş) LLVM-IR'ye baktığımızda, üçüncü versiyonda [[Box<i32>; 5]; 5] türüyle sonuçlanan tek temel farkların meydana geldiğini buldum. Yanlışlıkla böyle bir tür yaratabileceğimi görebiliyorum, ancak üçüncü bir sürümü özellikle böyle bir hata için kontrol ettim ve bulamıyorum.

+0

Ah, boşver o zaman, o zaman devam. – delnan

+0

güvenli sürümü U ile [T; N] iyi çalışıyor: http://is.gd/enk0I3 –

cevap

2

#[unsafe_destructor] ile hata yaptığınıza inanıyorum. Bunun için kodunuzu azaltılmış:

#![feature(unsafe_destructor)] 

struct IntoIter<U> { 
    inner: Option<U>, 
} 

impl<T> Iterator for IntoIter<[T; 8]> { 
    type Item = T; 
    fn next(&mut self) -> Option<T> { None } 
} 

#[unsafe_destructor] 
impl<T> Drop for IntoIter<[T; 8]> { 
    fn drop(&mut self) { 
     // destroy the remaining elements 
     for _ in self.by_ref() {} 

     unsafe { std::intrinsics::forget(self.inner.take()) } 
    } 
} 

fn main() { 
    let arr = [1; 8]; 
    IntoIter { inner: Some(arr) }; 
} 

Sonra derlenmiş (rustc -g unsafe.rs) ve rust-lldb bunu koştu. Ben damla uygulanmasına ilişkin bir kesme noktası ayarlamak ve self çıktısı:

(lldb) p self 
(unsafe::IntoIter<[[i32; 8]; 8]> *) $0 = &0x7fff5fbff568 

Bunu tür parametresi fark gibi, diziler dizisi olduğunu düşündüğünü görebilirsiniz. Bu noktada, eğer düşersek, hafızayı yitireceğiz. Pas'ın hala bellekte düşüşü sıfırladığına inanıyorum, bu yüzden muhtemelen bazı keyfi bellek parçalarının üzerinde sıfır yazabiliriz. Iyi ölçmek için

:

rustc --verbose --version 
rustc 1.0.0-dev (cfea8ec41 2015-03-10) (built 2015-03-10) 
binary: rustc 
commit-hash: cfea8ec41699e25c8fb524d625190f0cb860dc71 
commit-date: 2015-03-10 
build-date: 2015-03-10 
host: x86_64-apple-darwin 
release: 1.0.0-dev 
+0

Karşılık gelen hatayı buldum: https://github.com/rust-lang/rust/issues/8142 –

İlgili konular