Hi,
This following problem is most likely due to my own
misunderstandings, but I've not been able to resolve it after staring
and scratching my head for quite a while. Here it is:
---------------Start code---------------
#include <ruby.h> #include <iostream> #include <string>
using namespace std;
void dontCrash(string s)
{
VALUE test = rb_str_new2( s.c_str( ) );
rb_gc_register_address(&test);
rb_gc( ); // Test if gc gets corrupted
rb_p( rb_str_new2(" stuff!!! ") );
rb_p( test );
rb_gc_unregister_address(&test);
}
int main ()
{
ruby_init ();
ruby_init_loadpath ();
dontCrash("puts 'test'");
ruby_finalize();
}
-------------- End code --------------------
The code (as reported by valgrind) always crashes on rb_gc( ).
Without the rb_gc( ), the code runs fine. It also crashes when
rb_register_address isn't called. This error has really got me
stumped, so any help is greatly appreciated.
It doesn't crash for me.
What platform (os, ruby version, compiler, etc.) are you using?
That's strange,
Im using gentoo linux, ruby version emerged is 1.8.0-r6, compiling command
is 'g++ testruby.cpp -g -lruby18 -I<ruby path>'
Ive checked the version of ruby by printing out the defines
RUBY_VERSION and RUBY_RELEASE_DATE, and the library/include matches up.
Ive just tried it with ruby 1.8.1-r6 and this dumps as well.
Hmm... This is stranger, it works with ruby 1.6.8. Has garbage collection
management methods changed in between versions?
Where in rb_gc() does the crash occur?
The following is from gdb, valgrind gives many errors, all related to
rb_gc and rb_gc_mark_locations, but it is very verbose:
Program received signal SIGSEGV, Segmentation fault.
0x4007c683 in rb_gc_mark_locations () from /usr/lib/libruby18.so.1.8
(gdb) bt #0 0x4007c683 in rb_gc_mark_locations () from /usr/lib/libruby18.so.1.8 #1 0x4007e156 in rb_gc () from /usr/lib/libruby18.so.1.8 #2 0x08048b18 in dontCrash(std::string) (s=Cannot access memory at address 0x0
) at testruby.cpp:12 #3 0x08048b8f in main () at testruby.cpp:22
ruby_init() calls Init_stack, so why should this be necessary?
Any why does it matter anyway whether the stack is properly initialized
jn this case, since the address is being registered with the garbage
collector? (and thus the object should be marked just fine)
Paul
···
On Tue, Jun 08, 2004 at 09:32:20AM +0900, nobu.nokada@softhome.net wrote:
> int main ()
> {
> ruby_init ();
VALUE dummy;
Init_stack(&dummy);
> ruby_init_loadpath ();
> dontCrash("puts 'test'");
> ruby_finalize();
> }
ruby_init() calls Init_stack, so why should this be necessary?
To adjust the stack boundary.
The stack frame inside Init_stack() called from ruby_init()
would be placed at lower address than one of dontCrash() , so
that `test' in it would be outside the region of GC target.
It works now Thanks for all the help, I don't think I would've
come across that solution on my own. I'm still struggling to understand
why 1.6.8-r10 didn't crash while 1.8* did, however.
-Godot
···
On Tue, 08 Jun 2004 13:03:19 +0900, nobu.nokada wrote:
Hi,
At Tue, 8 Jun 2004 12:24:31 +0900,
Paul Brannan wrote in [ruby-talk:102734]:
ruby_init() calls Init_stack, so why should this be necessary?
To adjust the stack boundary.
The stack frame inside Init_stack() called from ruby_init()
would be placed at lower address than one of dontCrash() , so
that `test' in it would be outside the region of GC target.
But test was marked with rb_gc_register_address(). Shouldn't that
function work with addresses that are not on the stack?
Paul
···
On Tue, Jun 08, 2004 at 01:03:19PM +0900, nobu.nokada@softhome.net wrote:
> ruby_init() calls Init_stack, so why should this be necessary?
To adjust the stack boundary.
The stack frame inside Init_stack() called from ruby_init()
would be placed at lower address than one of dontCrash() , so
that `test' in it would be outside the region of GC target.
But test was marked with rb_gc_register_address(). Shouldn't that
function work with addresses that are not on the stack?
this is when ruby mark the stack that it has a problem, but the example
was badly written for an embedded application because it call ruby
function without any protection (rb_protect(), etc)
At Tue, 8 Jun 2004 23:40:36 +0900,
Paul Brannan wrote in [ruby-talk:102783]:
> > ruby_init() calls Init_stack, so why should this be necessary?
>
> To adjust the stack boundary.
> The stack frame inside Init_stack() called from ruby_init()
> would be placed at lower address than one of dontCrash() , so
> that `test' in it would be outside the region of GC target.
But test was marked with rb_gc_register_address(). Shouldn't that
function work with addresses that are not on the stack?
I've understood that [ruby-talk:102597] doesn't crash when
rb_gc_register_address() is called, wrong?
At Mon, 7 Jun 2004 04:33:40 +0900,
Godot wrote in [ruby-talk:102597]:
···
It also crashes when rb_register_address isn't called.
Are you saying that I should rb_protect on rb_gc? Would that catch the
fault? That doesn't seem possible - but when it comes to ruby, Alot of
things that are seem impossible
This was only an example illustrating a problem I was having on a larger
application. It was by no means meant to be more than that, but I do
appreciate the warning.
-Godot
···
On Wed, 09 Jun 2004 00:35:37 +0900, ts wrote:
> But test was marked with rb_gc_register_address(). Shouldn't that
> function work with addresses that are not on the stack?
this is when ruby mark the stack that it has a problem, but the example
was badly written for an embedded application because it call ruby
function without any protection (rb_protect(), etc)
Are you saying that I should rb_protect on rb_gc? Would that catch the
fault? That doesn't seem possible - but when it comes to ruby, Alot of
things that are seem impossible
No, I was trying to say that your example was badly written. In an
embedded application, after the initialization phase you must *never* make
a call to a ruby function which is not protected with rb_protect(), or
what you want.
If ruby detect an error when it call a function, it will call longjmp()
and this can crash your application if you have not made a previous call
to rb_protect(), ...
If your application is well written, you don't need Init_stack()
That's correct, rb_gc_register_address doesn't prevent the crash, and the
more I read about Init_stack, the more I question why it even needs to be
called (although that does fix it).
At Thu, 10 Jun 2004 04:13:41 +0900,
Godot wrote in [ruby-talk:102983]:
That's correct, rb_gc_register_address doesn't prevent the crash, and the
more I read about Init_stack, the more I question why it even needs to be
called (although that does fix it).
Hmmm, rb_gc_register_address should do. Something other might
go wrong.