rb_raise 在嵌入式 C++ 中导致分段错误
rb_raise in embeded c++ cause Segmentation fault
我尝试将 ruby 解释器嵌入到我的程序中。
程序运行良好,但如果 ruby 获得异常(在 C 中或 ruby 本身),程序会因 SEGFAULT 而崩溃。
例如:
#include <iostream>
#include "Ruby/ruby.h"
#define RUBY_METH(method) reinterpret_cast< VALUE ( * ) ( ... ) >(method)
using namespace std;
int main(int argc, char** argv)
{
cout << "Hello world!" << endl;
ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();
rb_require("./init");//segfault by "raise"
rb_raise(rb_eArgError, "Lol");//If comment "raise" in init.rb, segfault
return 0;
}
init.rb
p "lol"
raise
控制台输出
Hello world!
"lol"
<main>: [BUG] Segmentation fault
ruby 1.9.3p551 (2014-11-13) [i386-mingw32]
-- Control frame information -----------------------------------------------
c:0001 p:0000 s:0002 b:0002 l:000c74 d:000c74 TOP
-- C level backtrace information -------------------------------------------
C:\WINDOWS\SYSTEM32\ntdll.dll(ZwWaitForSingleObject+0xc) [0x76fbe5fc]
C:\WINDOWS\System32\KERNELBASE.dll(WaitForSingleObject+0x12) [0x75bdad52]
[0x004b2789]
[0x00402106]
[0x00402f6f]
[0x004f9e90]
[0x004011ea]
C:\WINDOWS\SYSTEM32\ntdll.dll(LdrSetAppCompatDllRedirectionCallback+0x1ae9d) [0x76fee0bd]
在 windows
上使用 GNU GCC 编译
迟到的答案,但对于任何可能遇到此问题的人来说,未捕获的 Ruby 异常将使您的应用程序出现段错误。在您的应用程序中嵌入 Ruby 时,您需要使用 rb_protect
来捕获错误。
https://silverhammermba.github.io/emberb/c/#exceptions
If you’re compiling a library to be loaded by Ruby, you have it easy. Any exceptions raised in the API can be rescued as usual in your Ruby code. If you want to rescue an exception in the API, you can use rb_rescue2() which is similar to Ruby’s rescue.
...
If you’re embedding the Ruby interpreter in C, you need to be extremely careful when calling API functions that could raise exceptions: an uncaught exception will segfault the VM and kill your program. You could call rb_rescue2() with rb_eException, but there’s another approach for rescuing all exceptions:
rb_protect
我尝试将 ruby 解释器嵌入到我的程序中。 程序运行良好,但如果 ruby 获得异常(在 C 中或 ruby 本身),程序会因 SEGFAULT 而崩溃。 例如:
#include <iostream>
#include "Ruby/ruby.h"
#define RUBY_METH(method) reinterpret_cast< VALUE ( * ) ( ... ) >(method)
using namespace std;
int main(int argc, char** argv)
{
cout << "Hello world!" << endl;
ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK;
ruby_init();
ruby_init_loadpath();
rb_require("./init");//segfault by "raise"
rb_raise(rb_eArgError, "Lol");//If comment "raise" in init.rb, segfault
return 0;
}
init.rb
p "lol"
raise
控制台输出
Hello world!
"lol"
<main>: [BUG] Segmentation fault
ruby 1.9.3p551 (2014-11-13) [i386-mingw32]
-- Control frame information -----------------------------------------------
c:0001 p:0000 s:0002 b:0002 l:000c74 d:000c74 TOP
-- C level backtrace information -------------------------------------------
C:\WINDOWS\SYSTEM32\ntdll.dll(ZwWaitForSingleObject+0xc) [0x76fbe5fc]
C:\WINDOWS\System32\KERNELBASE.dll(WaitForSingleObject+0x12) [0x75bdad52]
[0x004b2789]
[0x00402106]
[0x00402f6f]
[0x004f9e90]
[0x004011ea]
C:\WINDOWS\SYSTEM32\ntdll.dll(LdrSetAppCompatDllRedirectionCallback+0x1ae9d) [0x76fee0bd]
在 windows
上使用 GNU GCC 编译 迟到的答案,但对于任何可能遇到此问题的人来说,未捕获的 Ruby 异常将使您的应用程序出现段错误。在您的应用程序中嵌入 Ruby 时,您需要使用 rb_protect
来捕获错误。
https://silverhammermba.github.io/emberb/c/#exceptions
If you’re compiling a library to be loaded by Ruby, you have it easy. Any exceptions raised in the API can be rescued as usual in your Ruby code. If you want to rescue an exception in the API, you can use rb_rescue2() which is similar to Ruby’s rescue.
...
If you’re embedding the Ruby interpreter in C, you need to be extremely careful when calling API functions that could raise exceptions: an uncaught exception will segfault the VM and kill your program. You could call rb_rescue2() with rb_eException, but there’s another approach for rescuing all exceptions:
rb_protect