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

嵌入式QuickJS项目实现registerCallback方法遇段错误求助

嵌入式QuickJS中实现registerCallback时的段错误排查与修复

你当前的实现思路方向是对的,但段错误大概率是内存非法访问或QuickJS引用计数/生命周期管理不当导致的,以下是具体排查点和修复方案:

1. 检查myClassData的初始化与旧回调释放

如果myClassData中的registeredCallback未初始化,或者存储新回调前未释放旧值,会导致野指针或重复释放:

  • 修复:初始化结构体时将registeredCallback设为JS_UNDEFINED,存储新回调前先释放旧值:
static JSValue myClass_addCallbackMethod(
    JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    auto* object = static_cast<myClassData *>(
        JS_GetOpaque2(ctx, this_val, myClassId));

    // 先校验实例有效性
    if (!object)
        return JS_ThrowTypeError(ctx, "Invalid Class instance");

    if (argc == 0 || !JS_IsFunction(ctx, argv[0]))
        return JS_ThrowTypeError(ctx, "Expected a function as argument");

    // 释放旧回调(避免内存泄漏/野指针)
    if (!JS_IsUndefined(ctx, object->registeredCallback)) {
        JS_FreeValue(ctx, object->registeredCallback);
    }

    // 复制并存储新回调(增加引用计数,防止被GC回收)
    object->registeredCallback = JS_DupValue(ctx, argv[0]);

    return JS_UNDEFINED;
}

2. 确认JS_GetOpaque2返回的指针有效性

如果myClassId与注册类时使用的ID不匹配,JS_GetOpaque2会返回空指针,此时访问object->registeredCallback直接触发段错:

  • 排查:检查myClassId是否是全局唯一的,且注册类(JS_NewClassID、JS_NewClass)时使用的是同一个ID变量,没有重复定义或类型错误。

3. 回调的生命周期与上下文一致性

如果在main.cpp中访问回调时,存在以下情况也会触发段错:

  • 访问时的JSContext与存储回调时的上下文不一致;
  • 回调的JSValue已被QuickJS的GC回收;
  • myClassData实例已被销毁但仍被访问。

修复要点:

  • 确保访问回调时使用的JSContext与存储时完全一致;
  • 在myClassData的析构函数/QuickJS类终结器中释放回调:
void myClass_finalizer(JSRuntime *rt, JSValue val) {
    myClassData* data = static_cast<myClassData*>(JS_GetOpaque(val, myClassId));
    if (data) {
        // 释放回调值
        JS_FreeValueRT(rt, data->registeredCallback);
        delete data;
    }
}
  • 初始化myClassData时必须给registeredCallback赋值:
myClassData* createMyClassData() {
    myClassData* data = new myClassData();
    data->registeredCallback = JS_UNDEFINED; // 强制初始化
    return data;
}

4. main.cpp中访问逻辑的校验

在main.cpp中访问前,必须先校验:

  • myClassData指针不为空;
  • registeredCallback不是JS_UNDEFINED或JS_NULL;
  • 操作在正确的JSContext下进行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:45:37