You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:16:16