2016-04-06 1 views
2

私は錆びた生涯の問題の周りに私の頭をラップしようと怒っています。次のコードを実行している場合:錆のスライスの所有権がそのスコープを超えています

use std::fs::File; 
use std::io::Read; 
use std::clone::Clone; 

const BUFSIZE : usize = 4096; 

struct LexBuf<T: Read> { 
    f: T, 
    buf: [u8; BUFSIZE], 
    tail: usize, 
    head: usize 
} 

impl <T : Read> LexBuf<T> { 
    fn fetch(&mut self) { 
     let keepSize = self.head - self.tail + 1; 
     let mut tmpBuf; 
     { 
      let tmpSlice = &self.buf[self.tail..self.head+1]; 
      tmpBuf = tmpSlice.clone(); 
     } 
     &mut self.buf[0..keepSize] 
      .clone_from_slice(tmpBuf); 
     let mut n = self.f 
      .read(&mut self.buf[keepSize..]).unwrap(); 
     if n < BUFSIZE - keepSize { 
      self.buf[keepSize+n] = 0; 
     } 
    } 
} 

を私は事実tmpSliceは独自のスコープ内にあることを期待して、私はその後self.buf借りることができますが、それはtmpSliceのボローことを言うように借りチェッカーが一致していないようですスコープはfn fetchで終了します。

+2

'clone'は所有しているコピーを作成しません。参照を参照するものではなく、参照先を指定するだけで、' to_owned' –

答えて

6

もちろん、tmpBufの有効期間は内部ブロックで終了しないため、同意しません。スライス上で呼び出されたclone()は、そのスライスのコピー、つまりポインタと長さのコピーを返します。すべての目的と目的のために、tmpSlice.clone()によって返されたスライスは、その寿命を含めてtmpSliceに相当します。外側のスコープ内のtmpBufに割り当てるため、内側のブロックのスコープよりも長持ちします。

実際に、Rustが許可していれば、コードが破損する可能性があります。clone_from_slice()ソースと宛先が重複する可能性があります。例えば、self.tail0,self.headの場合、たとえば10の場合、送信元と送信先は完全に重複します。

残念ながら、実行時に決定されたサイズと固定サイズのスタック・アレイを作成する方法はありませんので、これを回避する唯一の方法は、Vec<u8>を得るためにスライス上to_owned()又はto_vec()を呼び出して、ヒープ上のデータを割り当てることです。

また、構造体のサイズより小さくないことが保証されている第2固定長配列を割り当てて、一時的な領域として使用できます。そのためにはclone_from_slice()を2回使用する必要があります。

関連する問題