From: "José Augusto" Date: 2003-04-03T23:14:40+09:00 Subject: Strange behavior in C-declared global variable? Hi, I hope someone can help me. I'm trying to write some C extensions with the main objective of speeding up some tasks in Ruby. I'm relying on the README.ext file as well as in Chapter 17 of the 'Prog. Ruby' book from Thomas and Hunt. The question is about creating a global variable in C and see it in Ruby. This is documented in both those documents, but has a strange behavior when implementing. Perhaps I'm missing something. Here is the script I tried both with Ruby 1.8.0/2003-03-31 version and Ruby 1.6.8. The results are slightly different. I made a lot of experiments with the code below in the last few days and looked at the ruby sources (also the sources in extension modules) but I didn't see anything that could help me. The fact that the code runs differently in 1.6.8 and 1.8.0 appears to indicate some kind of different behavior. The script is: ------------------------------------------------ require 'inline' # use Inline module class Fake inline_c_raw %q[ static VALUE newvar(int argc, VALUE *argv, VALUE self) { VALUE temp; temp = rb_ary_new(); rb_ary_push(temp, rb_float_new(3.3)); rb_define_variable("$tempor", &temp); rb_global_variable(&temp); return Qnil; } ] end f = Fake.new() f.newvar() # calls newvar puts "****\n" puts $tempor.class puts $tempor[0] puts "****" puts self.id #puts global_variables.grep(/tem/) puts "****\n" puts $tempor.class puts $tempor[0] puts "****" puts self.id ---------------------------------------------- The C code created by the inline module is ---------------------------------------------- #include "ruby.h" static VALUE newvar(int argc, VALUE *argv, VALUE self) { VALUE temp; temp = rb_ary_new(); rb_ary_push(temp, rb_float_new(3.3)); rb_define_variable("$tempor", &temp); rb_global_variable(&temp); return Qnil; } VALUE cMod_Fake_newvar; void Init_Mod_Fake_newvar() { cMod_Fake_newvar = rb_define_module("Mod_Fake_newvar"); rb_define_method(cMod_Fake_newvar, "newvar", newvar, -1); } ---------------------------------------------- The result of running ruby-1.8.0 is the following ---------------------------------------------- [jasa@localhost rb]$ ruby z.rb **** Fixnum 0 **** 537799894 **** z.rb:37: [BUG] Segmentation fault ruby 1.8.0 (2003-03-31) [i686-linux-gnu] Aborted ---------------------------------------------- That is, the first time the class and value of $tempor are wrong. The second time, the examination of $tempor crashes Ruby. However, the variable is supposedelly global, and it is 'declared' to Garbage Collection mechanism with rb_global_variable(&temp). The segmentation fault appears to be related with GC. More strangely, if the line '#puts global_variables.grep(/tem/)' is uncommented, there is no segmentation fault although $tempor is still a Fixnum instead of an Array. Here is the result: ---------------------------------------------- [jasa@localhost rb]$ ruby z.rb **** Fixnum 0 **** 537799894 $tempor **** Fixnum 1 **** 537799894 ---------------------------------------------- But with Ruby1.6.8 (24-12-2002) the segmentation fault above never occurs, which means it is insensible to the line "puts global_variables.grep(/tem/)" being commented or not. However, the Fixnum instead of Array class of $tempor is still wrong with ruby 1.6.8... What am I overlooking here? Are there some extra 'declarations' I shall do to keep the variable global? (I didn't found much help in the Ruby sources and in sources of extensions...:-( Thanks in advance! Jose Augusto