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
相关产品推荐
相关产品推荐

