# C extension: VALUEs being collected too early

**URL:** <https://www.ruby-forum.com/t/c-extension-values-being-collected-too-early/170217>\
**Category:** Ruby\
**Created:** [June 14, 2009, 6:39am UTC](https://www.ruby-forum.com/t/c-extension-values-being-collected-too-early/170217 "2009-06-14T06:39:46Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![edenli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/9e8a1a/32.png) [@edenli](https://www.ruby-forum.com/u/edenli)\
**Post date:** [June 14, 2009, 6:39am UTC](https://www.ruby-forum.com/t/c-extension-values-being-collected-too-early/170217/1 "2009-06-14T06:39:46Z")

</div>

I’m writing a C extension which passes around structs that refer to  
Ruby VALUEs. During the course of execution, these VALUEs are  
assigned new Ruby strings, hashes or arrays (via the rb\_{str,hash,ary)  
\_new functions) through a series of callbacks. The problem is that it  
seems they’re getting collected too early before I have a chance to  
use the result.

I tried a few things to keep these VALUEs around (including calling  
rb\_gc\_mark directly on these objects), but the only thing that seems  
to prevent this early collection is by disabling the GC while my code  
is executing.

Is there something I can use to prevent these VALUEs from getting re-  
used without resorting to turning off the GC altogether?

Here’s some pseudo code to help further illustrate the issue:

typedef struct {  
VALUE value;  
// some other fields  
} MyStruct;

typedef struct {  
MyStruct \*\*structs;  
} MyOtherStruct;

VALUE my\_rb\_func(VALUE self) {  
MyOtherStruct \*other;  
Data\_Get\_Struct(rb\_iv\_get(self, “@other”), MyOtherStruct, other);  
other-\>structs[0]-\>value = rb\_hash\_new();

// This chain will allocate new MyStruct references and assign  
// new Ruby objects to MyStruct-\>value entries. The rb\_hash\_new()  
// won’t be affected other than using rb\_hash\_aset().  
start\_callback\_chain(other);

// without disabling gc, other-\>structs[0]-\>value is _not_ the  
original  
// hash this is true even if we don’t assign anything to subsequent  
// MyStruct-\>value  
}

---

<div class="post-metadata">

**Author:** ![edenli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/9e8a1a/32.png) [@edenli](https://www.ruby-forum.com/u/edenli)\
**Post date:** [June 14, 2009, 3:41pm UTC](https://www.ruby-forum.com/t/c-extension-values-being-collected-too-early/170217/2 "2009-06-14T15:41:47Z")

</div>

eden li wrote:

> is executing.
> 
> // new Ruby objects to MyStruct-\>value entries. The rb\_hash\_new()  
> // won’t be affected other than using rb\_hash\_aset().  
> start\_callback\_chain(other);
> 
> // without disabling gc, other-\>structs[0]-\>value is _not_ the  
> original  
> // hash this is true even if we don’t assign anything to subsequent  
> // MyStruct-\>value  
> }

Why do not use ruby array (rb\_array\_new) as MyOtherStruct?  
This may help (just need to keep one object instead of bunch of them…)

---

<div class="post-metadata">

**Author:** ![edenli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/9e8a1a/32.png) [@edenli](https://www.ruby-forum.com/u/edenli)\
**Post date:** [June 14, 2009, 7:31pm UTC](https://www.ruby-forum.com/t/c-extension-values-being-collected-too-early/170217/3 "2009-06-14T19:31:31Z")

</div>

On Jun 13, 2009, at 21:39 , eden li wrote:

> is executing.  
> See “3.3 Encapsulate C data into a Ruby object” in README.EXT in the  
> ruby source distribution.

---

<div class="post-metadata">

**Author:** ![edenli](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/9e8a1a/32.png) [@edenli](https://www.ruby-forum.com/u/edenli)\
**Post date:** [June 14, 2009, 6:34pm UTC](https://www.ruby-forum.com/t/c-extension-values-being-collected-too-early/170217/4 "2009-06-14T18:34:46Z")

</div>

On Jun 14, 6:41 am, Peter Z. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Why do not use ruby array (rb\_array\_new) as MyOtherStruct?  
> This may help (just need to keep one object instead of bunch of them…)

I may end up doing that, but this is puzzling behavior, and I’d like  
to figure out what’s causing subsequent object allocations in the  
callback chain to overwrite the original rb\_hash\_new(). I’d like to  
know for future reference what’s going on here.
