Re: [gtk-list] GLIB+win32 memory problem



On Fri, 9 Apr 1999, Jacob Christen wrote:

> I've written a little C++ wrapper for the GList object in glib (my class
> implements the GList struct) and by the nature of my implementation (and
> that of a linked list node) I've had to write my own "new" and "delete"
> operators which basically wrap g_list_alloc() and g_list_free()
> respectively.  this all works great as long as my subclass has no member
> variables (say, for instance, a node-level mutex)--the requested
> allocation size passed to "new" now is larger than sizeof(GList).  i've
> tried to rectify this by calling g_list_alloc and then g_realloc( which
> maps straight to system realloc ) which i now know is a big mistake
> because g_list_alloc uses g_mem_chunk_* stuff (via a GAllocator* type).
> i've tried taking a look at the g_mem_chunk_alloc (which is ultimately
> called by g_list_alloc) to see if there is any way i can _safely_ and
> _reliably_ let it know that i want a memory chunk no smaller than a
> certain size.  do i even need to worry about this? (e.g. does
> g_mem_chunk_alloc allocate more memory than say 32 bytes per chunk?
> regardless, how do i change this number within the g_list_alloc
> context?).
> 
> again, i should say that i came accross this error using glib 1.2.1 on
> win32.
> 
> (p.s.  using g_realloc=realloc on the memory returned from g_list_alloc
> generates an "invalid local heap ponter" maybe i should just try to
> sidestep this instead?  if so how?  i've tried with no success)

actually there's no way to circumvent the glist allocation pattern.
memchunks for say sizeof(xxx)=5 and prealloc=10 basically allocate
50 byte areas and return chunks as multiples of 5, offsetted from
the area's starting adress.

overriding g_list_alloc() and g_list_free[_1]() doesn't work as well, since
those functions are also called internally by e.g. g_list_prepend() or
g_list_remove(). the *only* way i could come up with to allocate list nodes
beyond the structure size required by glib would be an extension to the
GAllocator interface to add extra padding for each node, but that padding
would be appended at the end of each structure (and thus you had to special
case this usage for any interface that you piggy back to uses GAllocators)
and of course the constrains i outlined in an earlier mail on GAllocators,
would still apply (appended below).

i also doubt that this is a reasonable approach at things, if you need thread
locking, why don't you use one global mutex? as soon as you want to lock
single objects, code complexity doubles (or does that actually grow
exponentially? ;) because to update one GList node, you'd had to take care
of locking the ->prev and ->next nodes as well, and that gets you into the
matter of locking single objects in the right order to avoid deadlock
scenarios.
imho, you're better off defining+implementing your own structures/objects
once you want per node locking.

> 
> Jacob Christen
> 

---
ciaoTJ


From: Tim Janik <timj@gtk.org>
Message-Id: <199903222157.WAA27708%timj@gtk.org>
Date: Mon, 22 Mar 1999 22:57:57 +0100 (CET)
To: "'gtk-list@redhat.com'" <gtk-list@redhat.com>
Subject: [gtk-list] Re: Benchmarking glib (atleast GList) (was: how ca
 n I trust glib when it has so many memleaks?)

On Mon, 22 Mar 1999, Rostedt, Steven wrote:

>       I believe we ARE getting memory fragmentation
>       here!  This test makes a large allocations after
>       the glists have been made, and these allocations
>       do not fit in the segments that have been previously
>       available.
>
>       This is why I think it is critical to have an actual
>       free call that frees all the buffered lists.  There
>       are times when large amounts of data needs
>       to be allocated and will surpass the size
>       of the memory chunks.

if you have a certain portion of code that uses *lots* of GLists or
GNodes, and you know you'd better want to release all of them after
a short while, you'd want to use a GAllocator. pushing an allocator
into g_list will make all subsequent glist operations private to that
allocator's memory pool (and thus you have to take care to pop the
allocator again, before making any external calls):

GAllocator *allocator;
GList *list = NULL;
guint i;

/* set a new allocation pool for GList nodes */
allocator = g_allocator_new ("list heap", 1024);
g_list_push_allocator (allocator);

/* do some list operations */
for (i = 0; i < 4096; i++)
  list = g_list_prepend (list, NULL);
list = g_list_reverse (list);

/* beware to pop allocator befor calling external functions */
g_list_pop_allocator ();
gtk_label_set_text (GTK_LABEL (some_label), "some text");

/* and set our private glist pool again */
g_list_push_allocator (allocator);

/* do some list operations */
g_list_free (list);
list = NULL;
for (i = 0; i < 4096; i++)
  list = g_list_prepend (list, NULL);

/* and back out (while freeing all of the list nodes in our pool) */
g_list_pop_allocator ();
g_allocator_free (allocator);


>
>       Conclusion: This test I believe demonstrates
>       why my application when so long, and why
>       there should be a g_list_flush function.
>
>       I would write it but I don't know all the details
>       of how the chunks in the Glist are allocated.
>       I looked at the code and have a good idea,
>       but I don't want to assume anything :)
>
>       Steve.
>

---
ciaoTJ



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]