> > garray = g_array_new (FALSE, FALSE, sizeof (Machine));
> > for (i = 1; i < 10000; i++){
> > Machine *newMach = machine_new(i,"trd11","d11","joe");
> > g_array_append_val (garray, newMach);

> Two problems here: You pass a *pointer* to Machine, not
> a Machine, so a pointer is stored into garray. And newMach
> is probably never freed.
> You could copy the contents of newMach into the array,

I've never actually used GArray, but I'd expect that another alternative to 
either the options of using g_ptr_array, or copying the newly created machine 
into the array (with all the evils that idea comes with), would be to break the 
GObject pattern a little, by changing machine_new() into machine_init(), and 
taking the address of a machine struct as the first parameter.

This idea works particularly well if you know before hand, how many elements 
will be in the array.  Just create the array, set its size with 
g_array_set_size(), and then use your machine_init() on each element in turn.  
(Like I said, I've never actually used a GArray...  But it should work)  Having 
said that, though, GArray (or even GPtrArray) are only likely to be of any use 
if the number of elements in the array is likely to change while the program is 
running.  If the number of machines will remain constant while the program's 
running, then as long as it's size is known before you have to actually 
allocate the array (for instance, your data file says there'll be 10 machines, 
and then presents the data for each machine), you can simply allocate memory 
for all 10, store it in a pointer to a machine struct, and then just go ahead 
and use it as a regular array.  It saves the ugly g_array_index buisness, at 
the expense of having to do a little extra work yourself.

Alternatively, you can use this approach quite well by creating a statically 
allocated machine struct with default values, appending that to your GArray 
(which involves copying the template into the new space), and then calling 
machine_init() to properly set it up.  This approach is particularly nice if 
you do happen to have a number of fields that need to be initialised to default 
values, as it saves having to do it in the machine_init() function...  This 
isn't entirely "safe", because you have to be careful to make sure that you 
always call machine_init() on a copy of the template struct.  But I've used 
this general technique myself on a number of occasions quite successfully.

A third way to approach the issue, based on the machine_init() method, is to 
actually allocate the machine struct on the heap (a simple variable of type 
struct machine), fill it in with machine_init(), and then append that to the 
GArray.  The original struct's memory will be released automatically when the 
function ends.  You can even re-use the one struct to build several machines, 
as long as your machine_init() totally initialises every member of the struct 
(which means it's not particularly compatible with the previous approach).

If you decide to go with the GPtrArray method instead, which has a few (fairly 
minor) advantages and disadvantages of its own, you can still have both options 
available by making your machine_new() function allocate memory for a new 
machine, and then call machine_init() on it, passing through all the arguments. 
 That's basically what a GObject does anyhow.  The GObject type system 
allocates the memory, and gets all the ancestor types to initialise their parts 
of the memory, before yours gets to finish it off.


Fredderic

_______________________________________________
Join Excite! - http://www.excite.com
The most personalized portal on the Web!


_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Reply via email to