Lee*_*Gee 3 rust shadow-dom typescript wasm-bindgen
我的第一个Rust生产的WASM正在产生以下错误,我不知道如何进行调试。
wasm-000650c2-23:340 Uncaught RuntimeError: memory access out of bounds
at dlmalloc::dlmalloc::Dlmalloc::free::h36961b6fbcc40c05 (wasm-function[23]:670)
at __rdl_dealloc (wasm-function[367]:8)
at __rust_dealloc (wasm-function[360]:7)
at alloc::alloc::dealloc::h90df92e1f727e726 (wasm-function[146]:100)
at <alloc::alloc::Global as core::alloc::Alloc>::dealloc::h7f22ab187c7f5835 (wasm-function[194]:84)
at <alloc::raw_vec::RawVec<T, A>>::dealloc_buffer::hdce29184552be976 (wasm-function[82]:231)
at <alloc::raw_vec::RawVec<T, A> as core::ops::drop::Drop>::drop::h3910dccc175e44e6 (wasm-function[269]:38)
at core::ptr::real_drop_in_place::hd26be2408c00ce9d (wasm-function[267]:38)
at core::ptr::real_drop_in_place::h6acb013dbd13c114 (wasm-function[241]:50)
at core::ptr::real_drop_in_place::hb270ba635548ab74 (wasm-function[69]:192)
Run Code Online (Sandbox Code Playgroud)
上下文:从TypeScript自定义元素调用的最新Chrome,Rust wasm-bindgen代码,在影子DOM中的画布上运行。呈现到画布上的数据来自HTML5 AudioBuffer。所有rust变量都在本地范围内。
如果文档中仅出现一个实例,则Web组件可以正常工作,但是如果再出现其他实例,则如上所述将转储堆栈跟踪。该代码运行没有任何其他问题。
我知道Chrome中存在突出的内存错误-这是它们的外观吗,还是有经验的锈/毛病开发人员可以告诉我这是否异常?
js-sys = "0.3.19"
wasm-bindgen = "0.2.42"
wee_alloc = { version = "0.4.2", optional = true }
[dependencies.web-sys]
version = "0.3.4"
Run Code Online (Sandbox Code Playgroud)
rust代码很小,仅将AudioBuffer的两个通道呈现到提供的HTMLCanvasElement:
#[wasm_bindgen]
pub fn render(
canvas: web_sys::HtmlCanvasElement,
audio_buffer: &web_sys::AudioBuffer,
stroke_style: &JsValue,
line_width: f64,
step_size: usize,
) {
// ...
let mut channel_data: [Vec<f32>; 2] = unsafe { std::mem::uninitialized() }; // !
for channel_number in 0..1 {
channel_data[channel_number] = audio_buffer
.get_channel_data(channel_number as u32)
.unwrap();
}
// ...
Run Code Online (Sandbox Code Playgroud)
我尝试注释掉功能,并且如果代码未触及画布但执行了上述操作,则会收到错误消息。进行以下更改将导致一个简单的“内存不足”错误。音频文件为1,200 k。
let channel_data: [Vec<f32>; 2] = [
audio_buffer.get_channel_data(0).unwrap(),
audio_buffer.get_channel_data(1).unwrap()
];
Run Code Online (Sandbox Code Playgroud)
编辑:out of memory对于上面的正确代码,后一个错误确实使我失望,但这实际上是Chrome错误。
您的问题是您创建了一块未初始化的内存,并且未正确初始化它:
let mut channel_data: [Vec<f32>; 2] = unsafe { std::mem::uninitialized() };
for channel_number in 0..1 {
channel_data[channel_number] = audio_buffer
.get_channel_data(channel_number as u32) // no need for `as u32` here btw
.unwrap();
}
Run Code Online (Sandbox Code Playgroud)
Ranges(aka a..b)在Rust中是专有的。这意味着您的循环不会像您想的那样重复两次,而是只循环一次,并且您有一个未初始化的循环Vec<f32> ,然后在删除循环时会感到恐慌。(请参阅Matthieu M.的回答以获取适当的解释)
这里有几种可能性。
0..20..=1let mut channel_data: [Vec<f32>; 2] = Default::default()
Run Code Online (Sandbox Code Playgroud)
这将正确初始化两个Vecs。有关如何初始化数组的更完整的概述,请参见初始化固定长度数组的正确方法是什么?
附带说明:避免使用unsafe,特别是如果您不熟悉Rust。
这里有两个问题:
0..1迭代[0](这是唯一的)。让我们一次检查一次。
unsafe。通常,您应努力避免unsafe。使用它的原因很少,而错误使用的方法也很多(例如此处)。
问题。
在这种情况下:
let mut channel_data: [Vec<f32>; 2] = unsafe { std::mem::uninitialized() };
for channel_number in /*...*/ {
channel_data[channel_number] = /*...*/;
}
Run Code Online (Sandbox Code Playgroud)
有两个问题:
std::mem::uninitialized是出于安全原因,不推荐使用; 使用它是一个非常糟糕的主意。其替换为MaybeUninitialized。Rust中没有赋值运算符,为了执行赋值,该语言将:
删除认为Vec是“ 原始行为”的原始内存;在这种情况下,可能的效果是读取并释放了一些随机指针值。这可能会崩溃,这可能会释放无关的指针,从而导致后者崩溃或内存损坏,这是BAD。
解决方案。
这里没有理由使用unsafe:
Default实现Vec不会分配内存。简而言之:
auto create_channel = |channel_number: u32| {
audio_buffer
.get_channel_data(channel_number)
.unwrap()
};
let mut channel_data = [create_channel(0), create_channel(1)];
Run Code Online (Sandbox Code Playgroud)
简单,安全且最有效。
If you insist on two-step initialization, then use iterators rather than indexing to avoid off-by-one errors.
In your case:
let mut channel_data = [vec!(), vec!()];
for (channel_number, channel) = channel_data.iter_mut().enumerate() {
*channel = audio_buffer
.get_channel_data(channel_number as u32)
.unwrap();
}
Run Code Online (Sandbox Code Playgroud)
There are many utility functions on Iterator, in this particular case, enumerate will wrap the item returned by iter_mut() (a &mut Vec<f32>) into a tuple (usize, &mut Vec<32>):
| 归档时间: |
|
| 查看次数: |
143 次 |
| 最近记录: |