From: Paul Brannan Date: 2002-10-23T00:30:16+09:00 Subject: Re: rb_gc_register_address problem On Tue, Oct 22, 2002 at 11:57:05PM +0900, William Djaja Tjokroaminata wrote: > In this case then what you want is probably something like > > std::vector foo; > void func(int argc, VALUE * argv, VALUE self) { > int length; > char *str; > rb_str2cstr (argv[0], &length); > str = malloc (sizeof(char) * (length + 1)); > strcpy (str, STR2CSTR(argv[0])); > foo.push_back(str); > } This is one possible solution. We went a different route, but thanks for the suggestion. Note, though, that this is not exception-safe. vector::push_back can throw an exception (std::bad_alloc). If it does, then str is left allocated. One solution is to push a dummy onto the vector before allocating memory. Using your helper fuction: std::vector foo; void func(int argc, VALUE * argv, VALUE self) { foo.push_back(0); foo[foo.length()-1] = create_str_from_rubystr (argv[0])); } The solution we went with was to leave the memory allocation to Ruby. I prefer to let Ruby's GC handle as much memory as possible, so that I don't have to worry quite so hard about exception-safety. The only exceptions to this rule I see are: 1) If I have many objects being allocated, I allocate them myself 2) If I have resources allocated other than memory (such as open files or sockets), I also handle that myself. > My philosophy in Ruby-C integration: separate the C-part and the Ruby-part > as much and as far as possible; we are better-off in the long run this > way. I agree. This is particularly important if the API ever changes. It also allows porting extensions easily to other languages. This is part of the philosophy behind SWIG. Paul