You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过WASM从JS直接访问C结构体内存偏移出错,如何排查?

问题:WASM中访问C结构体Union字段返回无效数据

用户定义了以下C结构体与枚举:

typedef struct {
    ValueType type;
    union {
        bool boolean;
        double number;
        Obj* obj;
    } as;
} Value;
typedef enum {
    VALUE_BOOL,
    VALUE_NIL,
    VALUE_NUMBER,
    VALUE_OBJ
} ValueType;

通过WASM,用户在js_library.js中实现了C声明的extern void accessStruct(Value value);函数,初始实现可正确打印ValueType字段的整数值。但用户修改代码后:

function accessStruct(value) {
  console.log(Module.getValue(value, "i32"));
  const v = value + 32;
  console.log(Module.getValue(v, "i64"));
}

用户认为ValueType占4字节(32位),当类型为VALUE_NUMBER时,通过上述代码应能读取union中的double值,但实际得到无效数据,需排查错误原因。

错误原因分析

  • 混淆位与字节的概念:你把ValueType的32位宽度直接当成了32字节的偏移量——32位等于4字节,union字段的起始偏移不可能是32字节,这是最基础的概念错误。
  • 结构体内存对齐的影响:C编译器会对结构体成员做内存对齐优化。你的Value结构体中,union里最大的成员是double(8字节)或Obj*(WASM LP64模型下为8字节),因此整个结构体的对齐单位是8字节。type字段仅占4字节,编译器会在它后面填充4字节的空白,让union字段的起始地址对齐到8字节边界。也就是说,union的起始偏移是value + 8,而非你以为的value + 4,更不是value + 32。
  • 数据类型读取错误:你用i64类型读取double值,double是64位浮点类型,和64位整数的二进制编码完全不同,强行按整数读取必然得到无效数据。

修正示例

如果要读取number字段,正确的代码应该是:

function accessStruct(value) {
  const type = Module.getValue(value, "i32");
  console.log(type);
  if (type === /* VALUE_NUMBER对应的枚举数值 */) {
    // union起始偏移为8字节,按double类型读取
    const num = Module.getValue(value + 8, "double");
    console.log(num);
  }
}

内容的提问来源于stack exchange,提问作者redixhumayun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:56:06