mti
mti

Reputation: 233

Understanding memory allocation in `wasm-bindgen`

Context

I'd like to improve my understanding of memory management and the usage of function free with wasm-bindgen. My understanding is that anything allocated must be freed. In particular this should hold for values passed from JS into Rust.

Example

In the docs, there is an example where a &str is passed from JS to Rust, and indeed is freed at the end, as expected.

export function greet(arg0) {
  const [ptr0, len0] = passStringToWasm(arg0);
  try {
    const ret = wasm.greet(ptr0, len0);
    const ptr = wasm.__wbindgen_boxed_str_ptr(ret);
    const len = wasm.__wbindgen_boxed_str_len(ret);
    const realRet = getStringFromWasm(ptr, len);
    wasm.__wbindgen_boxed_str_free(ret);
    return realRet;
  } finally {
    wasm.__wbindgen_free(ptr0, len0);
  }
}

This is generated from the following Rust code.

#[wasm_bindgen]
pub fn greet(a: &str) -> String {
    ...
}

Counterexample?

However, in the following function, which is also generated by wasm-bindgen, a Uint32Array is passed to wasm, whereby memory is allocated, but seemingly this memory is not freed at the end of the function.

module.exports.generate_key = function(seed, sid, pid, counterparties, t) {
    _assertClass(seed, RngSeed);
    var ptr0 = seed.ptr;
    seed.ptr = 0;
    const ptr1 = passArray32ToWasm0(counterparties, wasm.__wbindgen_malloc);
    const len1 = WASM_VECTOR_LEN;
    const ret = wasm.generate_key(ptr0, sid, pid, ptr1, len1, t);
    return takeObject(ret);
};

This is generated from the following Rust code.

#[wasm_bindgen]
pub async fn generate_key(
    seed: RngSeed,
    sid: u64,
    pid: u32,
    counterparties: &[u32],
    t: usize,
) -> Result<KeyShare, Error> {
    ...
}

Question

Why is the memory allocated in passArray32ToWasm0 seemingly not freed here?

Upvotes: 6

Views: 611

Answers (1)

Yilmaz
Yilmaz

Reputation: 49180

When you pass an array from Rust to JavaScript, the memory is still owned by Rust. If you want to free the memory after using it in JavaScript, you need to communicate this back to Rust. One way to achieve this is by using a callback mechanism to inform Rust that the memory is no longer needed in JavaScript, and then Rust can free the memory accordingly.

Basically, for what ever object you are passing to js, you also have to write a clean up function to clean the memory and in js side, you call this callback after you used the object

Upvotes: 0

Related Questions