2015-03-11 35 views
5

मैं [T; N] के लिए लागू करने की कोशिश कर रहा था। मैंने Default और swap (PlayPen) का उपयोग करके एक पूरी तरह से सुरक्षित संस्करण लिखा है। फिर मैंने इसे uninitialized, ptr::copy, Drop और forget (PlayPen) का उपयोग करने के लिए पोर्ट किया। मेरे इटरेटर struct इस तरह दिखता है:[टी; के बीच क्या अंतर है; एन] और यू अगर यू हमेशा [टी; एन]?

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

जब से मैं N का मूल्य प्रति एक इटरेटर struct बनाने के लिए नहीं करना चाहता था, मैं

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

जाहिर करने के लिए struct बदल रहा Iterator समायोजित करने के लिए किया था और Drop कार्यान्वयन (PlayPen)।

लेकिन अब मैंने किसी भी तरह से अपरिभाषित व्यवहार पेश किया है। पैनिक्स println एस, अनुकूलन स्तर या राशि चक्र संकेतों के आधार पर होता है या नहीं।

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) 

या तो मेरी दूसरी कार्यान्वयन पहले से ही अपरिभाषित व्यवहार दिखाता है, या वहाँ दूसरे और तीसरे कार्यान्वयन के बीच एक अंतर है। जेनरेट (अनुकूलित नहीं) एलएलवीएम-आईआर को देखते हुए, मैंने पाया कि केवल मौलिक अंतर तीसरे संस्करण में होते हैं जो [[Box<i32>; 5]; 5] प्रकारों के साथ समाप्त होता है। मैं देख सकता हूं कि मैं गलती से इस तरह का एक प्रकार कैसे बना सकता हूं, लेकिन मैंने विशेष रूप से इस तरह की गलती के लिए तीसरे संस्करण की जांच की और इसे नहीं मिला।

+0

ओह, कोई बात नहीं तो, तो पर ले जाने के। – delnan

+0

यू के साथ सुरक्षित संस्करण [टी; एन] ठीक काम करता है: http://is.gd/enk0I3 –

उत्तर

2

मुझे विश्वास है कि आप #[unsafe_destructor] के साथ कुछ बग मार रहे हैं। मैं इस के लिए अपने कोड कम:

#![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) }; 
} 

मैं तो संकलित (rustc -g unsafe.rs) और rust-lldb में यह भाग गया। मैं ड्रॉप कार्यान्वयन पर एक ब्रेकपाइंट सेट करें और यह मुद्रित self:

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

आप देख सकते हैं यह सोचता है कि उस प्रकार पैरामीटर सरणियों की एक सरणी है, तो आप सिर्फ तरह देखा। इस बिंदु पर, अगर हम वास्तव में ड्रॉप करते हैं तो हम स्मृति को कचरा करने जा रहे हैं। मेरा मानना ​​है कि जंग अभी भी बूंद पर स्मृति को याद करती है, इसलिए हम संभवतः स्मृति के कुछ मनमाने ढंग से खंडों पर शून्य लिख सकते हैं।

अच्छा उपाय के लिए:

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

मुझे संबंधित बग मिला: https://github.com/rust-lang/rust/issues/8142 –

संबंधित मुद्दे