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

Ruby C API定义Integer方法后触发段错误,$!为nil时如何处理异常?

C调用Ruby脚本添加方法后触发段错误的解决方法

初始代码与运行结果

C调用代码

#include <ruby.h>

int main(void) {
  ruby_init();

  int status;
  rb_load_protect(rb_str_new2("./test.rb"), 0, &status);

  if (status) {
    VALUE rbError = rb_funcall(rb_gv_get("$!"), rb_intern("message"), 0);
    printf("%s\n", StringValueCStr(rbError));
  }

  ruby_finalize();
  return status;
}

Ruby脚本(test.rb)

1.hello

初始运行输出

undefined method `hello' for 1:Integer

修改后的代码与错误

添加hello方法定义并挂载到Integer类后,修改后的C代码片段:

VALUE hello(VALUE self) {
  return Qnil;
}

// 在ruby_init()后添加
rb_define_method(rb_cInteger, "hello", hello, 0);

此时运行程序触发段错误:

ruby: [BUG] Segmentation fault at 0x00000000000000b0
/* ... */

且全局变量$!为nil,无法捕获错误信息。

问题原因与解决方法

问题原因

ruby_init()仅完成Ruby VM的基础初始化,核心类(如rb_cInteger)的完整初始化依赖加载路径的设置。直接在ruby_init()后调用rb_define_method挂载方法到Integer类,此时rb_cInteger指向的内存未完全初始化,访问时会触发段错误。此外,该错误发生在Ruby脚本执行前的VM初始化阶段,异常机制未就绪,因此$!为nil。

解决方法

在ruby_init()之后添加ruby_init_loadpath(),初始化Ruby核心库的加载路径,确保核心类完全可用:

修改后的完整C代码:

#include <ruby.h>

VALUE hello(VALUE self) {
  return Qnil;
}

int main(void) {
  ruby_init();
  ruby_init_loadpath(); // 初始化核心库加载路径,确保rb_cInteger等常量有效

  rb_define_method(rb_cInteger, "hello", hello, 0);

  int status;
  rb_load_protect(rb_str_new2("./test.rb"), 0, &status);

  if (status) {
    VALUE rbError = rb_funcall(rb_gv_get("$!"), rb_intern("message"), 0);
    printf("%s\n", StringValueCStr(rbError));
  }

  ruby_finalize();
  return status;
}

运行修改后的代码,脚本1.hello会正常调用自定义的hello方法,不再触发段错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:55:22