< :the previous in number
^ :the list in numerical order
> :the next in number
P :the previous (in thread)
N :the next (in thread)
|<:the top of this thread
>|:the next thread
^ :the parent (reply-to)
_:the child (an article replying to this)
>:the elder article having the same parent
<:the youger article having the same parent
---:split window and show thread lists
| :split window (vertically) and show thread lists
~ :close the thread frame
.:the index
..:the index of indices
Hi,
After examining the code further, our inconsistency happened because I did
not give exactly the correct example. Instead of just struct/class
inside another struct/class, it is struct/class inside a struct inside a
struct/class.
Therefore, in the outer struct/class there is a pointer. I allocate
memory for this pointer. When I try to initialize this newly allocated
memory, the gc gets invoked. So I guess both of us are actually correct:
1) In Data_Make_Struct Ruby fills the resulting struct with zeros.
2) Because Data_Make_Struct (or even Data_Wrap_Struct) may invoke gc, when
we initialize struct members with Data_Make_Struct, we have to do "double
initialization".
Actually the problem is much more general than this. Before we call any
Ruby function that may invoke gc (such as the innocent looking rb_str_new2
()), we have to make sure that all our data are initialized
properly. This was tricky because it occured inside my initialization
function itself. What I mean is, in C usually I do this:
ptr = (my_type*) malloc (sizeof (my_type));
ptr->data1 = val;
ptr->data2 = rb_str_new2 (...);
...
Now, in Ruby, I have to change my habit to
ptr = (type*) malloc (sizeof (type));
/* Fill in with some generic, default values */
ptr->data1 = 0;
ptr->data2 = Qfalse;
...
/* Fill in with the actual data */
ptr->data1 = val;
ptr->data2 = rb_str_new2 (...); /* may invoke gc */
...
Well, I guess so far the codes that I have dealt with are not as
convoluted as the gc concept. On the other hand, this supports my
assertion that ALLOC () is much more dangerous than malloc (). In ALLOC,
we have to make sure that all data are already proper; in malloc () there
is no possibility of jumping around at that point. Finally, because
Data_Make_Struct really calls ALLOC, then Data_Make_Struct is
indeed dangerous.
Regards,
Bill
============================================================================
nobu.nokada / softhome.net wrote:
>> ---------------------------------------------------
>> > It sounds strange. Data_Make_Struct() fills the allocated
>> > structure with 0 and rb_gc_mark() ignores 0 which is equal to
>> > Qfalse.
>> ---------------------------------------------------
>> I think this can only happen when we have a struct/class inside
>> another struct/class. What I observed is, while we are creating the
>> inner struct/class, gc gets called and try to mark the outer
>> struct/class. Are you saying that even in this case it is safe
>> because the outer struct/class should all be filled with zeros?
> Yes, I guess so.
>> Based on your response above, are you saying that this
>> "double-initializing" is actually not needed? (in which case, the
>> error is actually generated somewhere else?)
> It should be in Data_Make_Struct().