这篇文章是我之前文章的延续:(通过 C api 从 C 代码调用 ruby regex 不起作用)
我做了一些修改,现在我用“*”调用 rb_reg_regcomp。
#include <ruby.h>
#include "ruby/re.h"
#define MAX_INPUT_SIZE 1000
int main(int argc, char** argv) {
VALUE x;
char string[MAX_INPUT_SIZE];
int result;
result = ruby_setup();
ruby_init();
ruby_init_loadpath();
memset(string, 0, MAX_INPUT_SIZE);
fgets(string, MAX_INPUT_SIZE, stdin);
if (string[MAX_INPUT_SIZE-2]) {
return 0;
}
//printf("thing");
x = rb_str_new_cstr("*");
rb_reg_regcomp(x);
return 0;
}
现在当我运行这个程序然后按回车键时,我在 gdb 中得到这个:
Program received signal SIGSEGV, Segmentation fault.
0x000055555565bef6 in rb_ec_tag_jump (st=st@entry=RUBY_TAG_RAISE, ec=<optimized out>) at ../eval_intern.h:161
161 ec->tag->state = st;
(gdb) where
#0 0x000055555565bef6 in rb_ec_tag_jump (st=st@entry=RUBY_TAG_RAISE, ec=<optimized out>) at ../eval_intern.h:161
#1 0x0000555555661fe0 in rb_longjmp (ec=ec@entry=0x6160000000d0, tag=tag@entry=6, mesg=<optimized out>, mesg@entry=140737288676920, cause=<optimized out>, cause@entry=36) at ../eval.c:658
#2 0x000055555566231d in rb_exc_exception (mesg=mesg@entry=140737288676920, tag=tag@entry=6, cause=cause@entry=36) at ../vm_core.h:1866
#3 0x0000555555668628 in rb_exc_raise (mesg=mesg@entry=140737288676920) at ../eval.c:684
#4 0x00005555559387a5 in rb_reg_raise_str (err=<optimized out>, options=0, str=140737288677040) at ../re.c:3300
#5 rb_reg_init_str (options=0, s=140737288677040, re=140737288677000) at ../re.c:3300
#6 rb_reg_new_str (options=0, s=140737288677040) at ../re.c:3291
#7 rb_reg_regcomp (str=140737288677040) at ../re.c:3373
#8 0x000055555565aca1 in main () at ../eval.c:856
如何从 C 代码中适当地调用 ruby 正则表达式函数,以免发生崩溃?提前致谢!
编辑:我从源代码编译了 ruby 库。我正在使用提交 a8e7fee80129b0ba360c2671582117c8e18a6464 .
Edit2:我知道“*”不是有效的正则表达式,但该程序的最初目的是让用户键入自己的正则表达式,然后让 ruby 代码编译正则表达式。这段代码将用于模糊器,模糊 ruby 正则表达式解析器以查找其中的错误,因此该程序应该能够优雅地处理无效的正则表达式字符串而不是崩溃。
Edit3:从对 rb_str_new_cstr 的调用中删除换行符。仍然崩溃。
是的,在阅读文档后我修复了代码。这段代码(我认为)完美运行:
#include <ruby.h>
#include "ruby/re.h"
#define MAX_INPUT_SIZE 120
VALUE handle_error(VALUE obj1) {
return 0;
}
VALUE dangerous_func(VALUE x)
{
/* code that could raise an exception */
int thing;
thing = rb_reg_regcomp(x);
printf("Regex return value: %d\n", thing);
return thing;
}
int main(int argc, char** argv) {
VALUE x;
VALUE result;
int state = 0;
char string[MAX_INPUT_SIZE];
ruby_setup();
ruby_init();
ruby_init_loadpath();
state = 0;
memset(string, 0, MAX_INPUT_SIZE);
fgets(string, MAX_INPUT_SIZE, stdin);
if (string[MAX_INPUT_SIZE-2]) {
return 0;
}
x = rb_str_new_cstr(string);
result = rb_protect(dangerous_func, x, &state);
printf("result %d\n", state);
return 0;
}
感谢@pmacfarlane 提供的信息!