【问题标题】:Segmentation fault when calling a Ruby function using C api使用 C api 调用 Ruby 函数时出现分段错误
【发布时间】:2016-07-23 02:25:29
【问题描述】:

我正在尝试使用 Ruby C API 调用简单的 ruby​​ 函数,执行编译输出时出现分段错误,我不确定是什么问题,希望您能帮助我,谢谢。

C 代码 (./func.c)

#include <ruby.h>
int main(){
 VALUE obj;
 VALUE result;
 VALUE map;
 ruby_init();
 rb_require("./func.rb");
 obj=rb_str_new_cstr("");
 map = rb_hash_new();
 rb_hash_aset(map, rb_str_new2("key"),rb_str_new2("val"));

 result = rb_funcall(obj, rb_intern("func"), 1, map);
 return 0;
}

Ruby 代码 (./func.rb)

def func(opts)
    puts opts['key']
end

编译标志

gcc func.c -o func -I/home/wh/.rbenv/versions/2.1.6/include/ruby-2.1.0/x86_64-linux -I/home/wh/.rbenv/versions/2.1.6/include/ruby-2.1.0 -L/home/wh/.rbenv/versions/2.1.6/lib/ -lruby-static -lm -pthread -lcrypt -ldl -rdynamic

运行./func时出现分段错误

<main>: [BUG] Segmentation fault at 0x00000000000018
ruby 2.1.6p336 (2015-04-13 revision 50298) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0001 p:0000 s:0002 E:002468 TOP    [FINISH]


-- C level backtrace information -------------------------------------------
./func() [0x581bcc] vm_dump.c:690
./func() [0x5f4893] error.c:312
./func(rb_bug+0xb3) [0x5f5a73] error.c:339
./func() [0x4f6c83] signal.c:824
/lib/x86_64-linux-gnu/libpthread.so.0(+0x10340) [0x7f805628d340] ../nptl/sysdeps/pthread/funlockfile.c:29
./func() [0x416f03] eval_intern.h:157
./func(rb_require_safe+0x63c) [0x42038c] load.c:1017
./func(main+0x18) [0x418b05]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f8055ed9ec5] libc-start.c:287
./func() [0x418a23] enumerator.c:181

-- Other runtime information -----------------------------------------------

Segmentation fault (core dumped)

【问题讨论】:

  • 不管怎样,你的代码对我来说没问题,尽管使用不同的操作系统、编译器和 Ruby 版本(Mac、clang 和 Ruby 版本 2.3.0 和 2.2.3)。
  • 我刚刚尝试了 ruby​​ 2.2.3 + clang 3.4,但仍然遇到分段错误。
  • 似乎找不到./func.rb(可能是LoadError,但也可能是其他问题)。尝试将ruby_init() 调用之后的所有内容包装到一个函数中,然后将其传递给rb_protect(),否则引发异常可能会导致段错误。嵌入 MRI 存在许多缺陷。
  • 我将包装器添加到rb_requirerb_funcall,没有分段错误但它失败并且状态的值为6rb_protect(RUBY_METHOD_FUNC(rb_require), (VALUE) '"./func.rb",&amp;state);if(state){printf("rb_require Error %d\n",state); }

标签: c ruby segmentation-fault


【解决方案1】:

似乎缺乏如何嵌入 ruby​​ 的规范示例(至少在官方文档中)。我能找到的最好的东西是这个来自镐的free chapter,它说你需要

ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();

设置 ruby​​ 解释器。你错过了其中的一些,特别是考虑到你的崩溃发生在require 内部,缺少的ruby_init_loadpath 似乎很可疑。

this thread(其中 Dave Thomas 询问嵌入 ruby​​ 的更改)Nobu 还说你需要

RUBY_GLOBAL_SETUP

在main之前。

您可能还对 mruby 感兴趣,它的设计易于嵌入。

【讨论】:

  • 我尝试了你的建议,我遇到了同样的分段错误。
  • 完全一样的回溯?
  • 我想是的,gist.github.com/anonymous/6d147bc68490f24cc480b8bf37805756,顺便说一句,我收到了这个警告:数据定义在 RUBY_GLOBAL_SETUP 上没有类型或存储类 [默认启用];
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-08
相关资源
最近更新 更多