WebAssembly Table对象设置元素时为什么报错?
在用WebAssembly Table对象实现函数动态调用时卡住了。我初始化了一个table,但设置元素时总报错”Index or offset out of bounds”。
代码像这样写的:
const table = new WebAssembly.Table({ initial: 10, element: "anyfunc" });
table.set(0, myFunc); // 这里报错说索引超出范围
明明初始大小是10,为什么索引0还越界?试过调整initial值但问题依旧,难道还要额外扩容吗?
解决办法是先调用 table.grow(10) 来真正分配空间,让 table.length 变成 10 之后,才能使用 table.set(0, myFunc)。
举个例子:
const table = new WebAssembly.Table({ initial: 10, element: 'anyfunc' });
table.grow(10); // 关键步骤,分配内存空间
table.set(0, myFunc); // 这时候才不会报错
因为 WebAssembly 要防止越界访问,保证内存安全,所以即使你声明了 initial 大小,也必须通过 grow 显式扩展 length 才能写入。
有点像数组你声明了个长度,但实际用的时候还要 push 或者设置 length,只不过 WebAssembly 这里要更严谨一点。这坑我也踩过,确实容易掉进去。
element的类型定义上。你用的是"anyfunc",这是 WebAssembly 1.0 中的老定义,在现代实现里已经被废弃了。正确写法应该是用{ element: "funcref", initial: 10 }。另外,“Index or offset out of bounds”通常是因为传入的值不是 WebAssembly 所认识的
WebAssembly.Function类型。即使你的myFunc是一个普通的 JavaScript 函数,也需要通过模块实例的导出环境包装一下才能放进去。这里给你个完整的例子:
需要注意的是,如果你真的在跟一个 Wasm 模块交互,记得要做校验,确保传入的函数符合模块期望的签名(参数和返回值类型)。不然可能会导致运行时崩溃或者未定义行为。这种情况下最好查看一下模块的导出信息或文档,明确函数签名。