«RuntimeError: доступ к памяти за пределами» при попытке сохранить строку в куче Wasm, а затем сохранить указатель на строку в структуре - PullRequest
0 голосов
/ 22 февраля 2020

Я пытаюсь сохранить строку в куче 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.

Это консольное сообщение, которое я получаю, когда запускаю это, а иногда и ошибку памяти. Console log

Ответы [ 2 ]

1 голос
/ 22 февраля 2020

В create вы создаете vec d и берете его указатель, но после завершения функции vec d освобождается и ваш указатель указывает на недопустимую память.

0 голосов
/ 23 февраля 2020

Так, наконец, я мог понять это. Ниже мое решение.

Код ржавчины:

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.

Есть ли лучший способ сделать это, помня о производительности.

...