2015-04-02 89 views
0

我的函數save_vec有一個問題,它使用mmap將矢量保存到磁盤。它創建了合適大小的文件,但是當我檢查其內容時(使用hexdump),它只是全零。 mmap使用MAP_SHARED而不是私有的,因此假設我的copy_nonoverlapping調用有問題。我的std :: ptr :: copy_nonoverlapping調用有什麼問題?

fn save_vec<T: Encodable + Debug + Copy>(path: &str, v: &Vec<T>) -> Option<String> { 
    println!("save_vec"); 
    let mut encoded: Vec<u8> = bincode::encode(v, SizeLimit::Infinite).unwrap(); 
    let len = encoded.len(); 
    println!("encoded = {:?}", encoded); 
    println!("len = {:?}", len); 
    let file = match OpenOptions::new() 
      .create(true) 
      .read(true) 
      .write(true) 
      .open(path) { 
     Ok(f) => f, 
     Err(err) => return Some("cannot create file".to_string()) 
    }; 
    file.set_len(len as u64); 

    let fd = file.as_raw_fd(); 
    unsafe { 
     let mmap_len = len as libc::size_t; 
     let prot = libc::PROT_READ | libc::PROT_WRITE; 
     let flags = libc::MAP_SHARED; 
     let ptr = libc::mmap(0 as *mut libc::types::common::c95::c_void, mmap_len, prot, flags, fd, 0); 
     if ptr == libc::MAP_FAILED { 
      return Some("mmap fail".to_string()) 
     } 
     let byte_ptr: *const u8 = mem::transmute(ptr); 
     let encoded_ptr: *mut u8 = encoded.as_mut_ptr(); 
     ptr::copy_nonoverlapping(byte_ptr, encoded_ptr, len); 
     libc::munmap(ptr, len as u64); 
     println!("byte_ptr={:?}", byte_ptr); 
    } 

    None 
} 
+0

也許與此有關? http://internals.rust-lang.org/t/memcpy-is-backwards/1797 – PEPP 2015-04-02 20:54:57

+0

你真的應該嘗試創建一個[MCVE](http://stackoverflow.com/help/mcve)。發佈使用(但不需要)外部庫的代碼,而省去所需的'use'語句,這些都使得我們很難幫助你。 – Shepmaster 2015-04-05 15:30:17

+0

這就足夠了嗎? – jimjampez 2015-04-05 15:53:51

回答

1

您可能正在被last-minute change to the argument order of ptr::copy and friends咬傷。具體來說,您的這部分代碼:

let byte_ptr: *const u8 = mem::transmute(ptr); // Why is this const? 
let encoded_ptr: *mut u8 = encoded.as_mut_ptr(); // Why is this mutable? 
ptr::copy_nonoverlapping(byte_ptr, encoded_ptr, len); 

編譯器實際上是給你一些跡象表明,什麼是錯,因爲你「需要」一個可變指針數據的來源。這沒有任何意義 - 我們只是從這個片段閱讀。而目的地是不變的,這意味着我們不能改變它

下面是完整的代碼,我跑了工作:

extern crate libc; 

use std::{mem,ptr}; 
use std::fs::OpenOptions; 
use std::os::unix::io::AsRawFd; 

fn save_vec(path: &str, v: &[u8]) -> Result<(), String> { 
    let len = v.len(); 

    let f = 
     OpenOptions::new() 
     .create(true) 
     .read(true) 
     .write(true) 
     .open(path); 

    let file = try!(f.map_err(|_| "cannot create file".to_string())); 
    file.set_len(len as u64).unwrap(); 

    let fd = file.as_raw_fd(); 
    unsafe { 
     let mmap_len = len as libc::size_t; 
     let prot = libc::PROT_READ | libc::PROT_WRITE; 
     let flags = libc::MAP_SHARED; 
     let ptr = libc::mmap(0 as *mut libc::types::common::c95::c_void, mmap_len, prot, flags, fd, 0); 
     if ptr == libc::MAP_FAILED { 
      return Err("mmap fail".to_string()) 
     } 
     let byte_ptr: *mut u8 = mem::transmute(ptr); 
     let encoded_ptr: *const u8 = v.as_ptr(); 
     ptr::copy_nonoverlapping(encoded_ptr, byte_ptr, len); 
     libc::munmap(ptr, len as u64); 
    } 

    Ok(()) 
} 

fn main() { 
    save_vec("dump", b"hello").unwrap(); 
} 
相關問題