[译]WebAssembly 中的 Memory
英文原文:https://hacks.mozilla.org/2017/07/memory-in-webassembly-and-why-its-safer-than-you-think/
这是系列文章:
WebAssembly中的内存与JavaScript中的内存有所不同。使用WebAssembly,您可以直接访问原始字节码…这可能令人担忧。但是,它的确比你想象中的要安全。
什么是 memory 对象?
当 WebAssembly 模块被实例化时,它需要一个 memory 对象。你可以创建一个新的WebAssembly.Memory并传递该对象。如果没有创建 memory 对象,在模块实例化的时候将会自动创建,并且传递给实例。
JS引擎创建一个ArrayBuffer(我在另一篇文章中解释)来做这件事情。ArrayBuffer 是 JS 引用的 JavaScript 对象。JS 为你分配内存。你告诉它需要多少内存,它会创建一个对应大小的ArrayBuffer。
数组的索引可以视为内存地址。如果你需要增加它的内存,你可以使用 grow
方法让数组变大。
ArrayBuffer 做了两件事情,一件是做 WebAssembly 的内存,另外一件是做 JavaScript 的对象。
它使 JS 和 WebAssembly 之间传递内容更方便。
使内存管理更安全。
JS 和 WebAssembly 之间传值
因为 ArrayBuffer 是一个 JavaScript 对象,这意味着 JavaScript 也可以获取到这个 memory 中的字节。所以通过这种方式, WebAssembly 和 JavaScript 可以共享内存,并且相互传值。
使用数组索引来访问每个字节,而不是使用内存地址。
比如,WebAssembly 想将一个字符串写入内存。它需要将字符串转换成字节码。
然后把这些字节码放进数组。
然后将字符串所在的内存位置的第一个位置,也就是数组的某个索引,传递给 JavaScript。JavaScript 可以根据索引从 ArrayBuffer 中拿到字符串
现在,很多人并不知道如何在 JavaScript 中使用字节码。你需要将字节码转换为有用的内容,比如说字符串。
在一些浏览器中,你可以使用TextDecoder和TextEncoderAPI来处理。或者你可以在你的js文件里添加一些帮助函数。比如,Emscripten就可以帮你添加编码和解码的方法。
所以,WebAssembly memory 最好的地方就是它是一个 JS 对象。WebAssembly 和 JavaScript 可以直接使用 memory 互相传值。
让 memory 存取更安全
另外一个好处是,WebAssembly memory 只是一个 JavaScript 对象:安全。通过防止浏览器级内存泄漏并提供内存隔离,使事情变得更安全。
内存泄漏
正如我在内存管理的文章中提到的,当你管理自己的内存时,你可能会忘记清除它。这可能导致系统内存不足。
如果 WebAssembly 模块实例直接访问内存,并且如果在超出范围之前忘记清除该内存,那么浏览器可能会泄漏内存。
因为内存对象只是一个JavaScript对象,所以它本身就被垃圾回收器跟踪(尽管它的内容不会垃圾回收)。
也就是说,WebAssembly 实例被移除以后,所有的内存数组将会被回收。
内存隔离
当人们听到WebAssembly让你直接访问内存时,他们可能有点紧张。他们认为,一个恶意的 WebAssembly 模块可能会进入并在内存中干坏事,这是绝对不允许的。但事实并非如此。
ArrayBuffer 提供了边界。WebAssembly 模块可以直接管理的内存是受限制的。
它可以直接管理该数组内部的字节,但它看不到任何超出此数组范围的内容。
例如,内存中的任何其它 JS 对象,如 window 对象,WebAssembly无法访问。这对安全性非常重要。
每当 WebAssembly 中有操作内存时,引擎会进行数组限制检查,以确保该地址位于 WebAssembly 实例的内存中。
如果代码尝试访问超出范围的地址,引擎将抛出异常。这保护了其它的内存。
所以这就是 memory 相关的内容。在下一篇文章中,我们将看研究一些关于安全性的其它类型的 import 数据:table import。
About
Lin 是Mozilla Developer Relations团队的工程师。她使用 JavaScript、WebAssembly、Rust 和 Servo,也画一些漫画。
版权声明
本博客文章均为 范明非 原创或翻译,采用知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。
原文地址: https://fanmingfei.com/posts/WebAssembly_Memory.html