"RuntimeError: доступ к памяти вне пределов" при попытке сохранить строку в куче Wasm с последующим сохранением указателя на строку в структуре
Я пытаюсь сохранить строку в куче Wasm как Uint8Array
после кодирования и сохранения указателя на строку и длины в Struct, чтобы я мог получить доступ к строке позже. Ниже мой код вrust
#[wasm_bindgen]
pub struct CustomString{
ptr : *const u8,
len: usize
}
#[wasm_bindgen]
impl CustomString{
pub fn create(len:usize) -> Self{
let mut d = Vec::with_capacity(len);
log!("{}",len);
CustomString{
ptr: d.as_ptr(),
len
}
}
pub fn as_ptr(&self) -> *const u8{
self.ptr
}
pub fn print_string(&self){
let js = unsafe { std::slice::from_raw_parts(self.ptr, self.len) };
let js = unsafe { std::str::from_utf8_unchecked(js) };
log!("{}",js)
}
}
Мой побочный код JS выглядит следующим образом:
function myTest (){
debugger;
const { memory } = wasm;
let encoder = new TextEncoder();
let mystring = "Ujjal";
let encodedString = encoder.encode(mystring);
let length = encodedString.length;
console.log(length)
let cs = CustomString.create(length);
let ptr = cs.as_ptr();
const asBytes = new Uint8Array(memory.buffer, ptr, length);
asBytes.set(encodedString);
return cs;
}
let cs = myTest();
function decode(cs){
cs.print_string();
}
decode(cs);
В идеале он должен печатать данную строку, но показывает какое-то несвязанное нежелательное значение. Не мог понять, что случилось, потому что я новичок в ржавчине и wasm.
Это консольное сообщение, которое я получаю, когда запускаю эту, а иногда и ошибку памяти.
2 ответа
В create
вы создаете vec d
и взяв его указатель, но после завершения функции vec d
освобождается, и ваш указатель указывает на недопустимую память.
Итак, наконец, я смог это понять. Ниже мое решение.
Код ржавчины:
pub struct CustomString{
ptr : *mut u8,
len: usize
}
#[wasm_bindgen]
impl CustomString{
pub fn create(len:usize) -> Self{
let mut d = String::with_capacity(len);
// log!("{}",len);
let ptr = d.as_mut_ptr();
std::mem::forget(d);
CustomString{
ptr,
len
}
}
pub fn as_ptr(&self) -> *mut u8{
self.ptr
}
pub fn as_string(&self)-> String{
let m = unsafe { String::from_raw_parts(self.ptr, self.len, self.len) };
m
}
pub fn print_string(&self){
let m = unsafe { String::from_raw_parts(self.ptr, self.len, self.len) };
log!("{}",m)
}
}
Код JS:
function myCS(string){
const { memory } = wasm;
let encoder = new TextEncoder();
let encodedString = encoder.encode(string);
let length = encodedString.length;
let cs = CustomString.create(length);
let ptr = cs.as_ptr();
const asBytes = new Uint8Array(memory.buffer, ptr, length);
asBytes.set(encodedString);
return cs;
}
Одна из проблем этого решения в том, что оно не очень эффективно. Я тестировал это с500000 random length strings
. Это занимает около4000+ ms
.
Есть ли лучший способ сделать это с учетом производительности.