我的std :: ptr :: copy_nonoverlapping调用出了什么问题?

时间:2015-04-02 17:54:58

标签: rust

我的函数save_vec出现问题,使用mmap将向量保存到磁盘。它创建的文件大小合适,但当我检查其内容时(使用hexdump),它只是全部为零。 mmap正在使用MAP_SHARED而不是私有,所以假设我的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
}

1 个答案:

答案 0 :(得分:2)

你可能被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);

编译器实际上给了你一些错误的指示,因为你需要&#34;指向数据源的 mutable 指针。这没有任何意义 - 我们只是从那个片段中读取。目的地是不变的,这意味着我们无法改变它

这是我运行的完整代码:

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();
}