Rust WASM内存指针与JS ArrayBuffer偏移不匹配问题求助
问题分析与解决方案
你的核心问题出在内存管理上:malloc_u8_array返回的是悬空指针,导致JS写入的内存区域在Rust读取时已经失效。
问题根源
在malloc_u8_array函数中,你创建了一个Vec<u8>后直接返回vec.as_ptr()。但Rust的Vec是栈上变量,函数执行完毕后会自动调用析构函数释放其堆内存。此时返回的指针指向的内存已经被WASM Runtime回收,属于野指针,后续JS写入、Rust读取的操作都是未定义行为,最终读取到全0数据就是内存被回收后的表现。
修正方案
方案1:手动管理内存所有权(保留指针操作逻辑)
通过Box<[u8]>替代Vec,使用Box::into_raw转移内存所有权,避免内存被提前释放:
#[wasm_bindgen] pub fn malloc_u8_array(size: usize) -> *mut u8 { utils::set_panic_hook(); // 将Vec转为Box<[u8]>,再转成原始指针,转移内存所有权 let boxed_slice = vec![128; size].into_boxed_slice(); Box::into_raw(boxed_slice) as *mut u8 } #[wasm_bindgen] pub fn load_data(ptr: *mut u8, size: usize) -> i32 { utils::set_panic_hook(); log(&format!("{:?}", ptr)); // 将原始指针转回Box<[u8]>,重新获取内存所有权 let boxed_slice = unsafe { Box::from_raw(std::slice::from_raw_parts_mut(ptr, size)) }; let u8array: Vec<u8> = boxed_slice.into(); log(&format!("{:?}", u8array)); log(&format!("{:?}", String::from_utf8(u8array).unwrap())); 0 }
方案2:使用wasm-bindgen原生类型(更简洁,避免手动指针操作)
直接借助js_sys::Uint8Array传递数据,无需手动管理指针:
use wasm_bindgen::JsCast; #[wasm_bindgen] pub fn load_data(buf: &js_sys::Uint8Array) -> i32 { utils::set_panic_hook(); // 将JS侧的Uint8Array复制到Rust Vec中(如需零拷贝可使用视图,但需保证JS侧不修改内存) let mut vec = vec![0; buf.length() as usize]; buf.copy_to(&mut vec); log(&format!("{:?}", vec)); log(&format!("{:?}", String::from_utf8(vec).unwrap())); 0 }
对应的JS代码可简化为:
wasm_app().then(output => { fetch("./data.json") .then(resp => resp.arrayBuffer()) .then(buf => { const uint8 = new Uint8Array(buf); output.load_data(uint8); }); });
内容的提问来源于stack exchange,提问作者NightmareRevisited
相关产品推荐
相关产品推荐

