Re: alloca (fwd)



Soliciting input on the best way to implement alloca-based functions in
GLib...  This is a forwarded response from TimJ, with his permission,
which has quoted the bulk of my proposal. 

	Jeff



---------- Forwarded message ----------
Date: Wed, 20 Jan 1999 01:38:26 +0100 (CET)
From: Tim Janik <timj@gtk.org>
To: Jeff Garzik <jgarzik@pobox.com>
Subject: Re: alloca

On Tue, 19 Jan 1999, Jeff Garzik wrote:

> What do you think about this as a rough implementation of alloca for
> glib 1.3:
> 
> #if G_HAVE_ALLOCA
> #  define g_malloc_a alloca
> #  define g_free_a(ptr) G_STMT_START G_STMT_END
> #else
> #  define g_malloc_a g_malloc
> #  define g_free_a g_free
> #endif
> 
> By simply requiring the programmer to free memory like they would
> without alloca, you provide a drop-in replacement without requiring some
> godawful alloca replacement implementation.

this doesn't work along nicely with real alloca() replacements that require
occasional calls to alloca(), also one of the important benefits of
alloca() usage is that you allocate the neccessary memory once and then
don't need to worry about freeing it again. this becomes very convenient
for code with multiple exit points, i.e.
{
  gchar *s1, *s2;
  gchar *p;
  
  p = some_static_string (rand ());
  s1 = alloca (strlen (p);
  *s1 = 0;
  strcpy (s1, p);
  p = some_static_string (rand ());
  s2 = alloca (strlen (p);
  *s2 = 0;
  strcpy (s2, p);
  
  setup_conditions_and_invalidate_all_static_strings ();
  
  if (condition1)
    return *s1 != 'x';
  else if (condition2)
    return s1[5] == s2[3];
  else switch (foo)
  {
  case 1: return s1[5];
  case 6: return s2[7];

...... you get the idea


so a g_malloc_a/g_free_a interface would actually defeat the purpose of
using alloca() somewhat. we rather should provide  

#if G_NATIVE_ALLOCA
#  define g_alloca alloca
#  define g_alloca_gc()		/* nothing to do for garbage collection */
#else /* !G_NATIVE_ALLOCA */
extern gpointer g_alloca (gulong size);
#  define g_alloca_gc()		g_alloca (0)
#endif /* !G_NATIVE_ALLOCA */

e.g. gettext-0.10.35/lib/alloca.c gives a good idea on how to implement
g_alloca(), there's a bunch of cruft to be stripped in it and it needs
to be adapted to the general glib style and feature glib's memory debugging
and profiling stuff, but it's certainly a good start.

as an aside, since glib already provides a loop implementation, we could
ease the burden on the alloca() using programmer by stuffing g_alloca_gc()
calls into g_main_run and/or g_main_iterate, so the average gtk/gnome
programmer doesn't even need to worry about alloca garbage collection
(gtk_signal_real_emit() is a good place for that as well).

> The g_strdup_a and similar macros would use g_malloc_a, and their values
> would be freed like normal malloc'd data.
> 
> I don't see any way around having to put the returned pointer into the
> argument list, though; AFAIK it is impossible to have a multi-statement
> macro be anything but a void statement (G_STMT_START, ...)

yeah, that's a tribut we have to pay for glib being portable to non-gcc
compilers.

note that we can't simply provide

#define g_strdupa(var, string)	{ code that alters the value of var }

since that's just a violation of how lower case macros and functions
are normally used, i.e. you'd never expect a normal function to alter
the value of one of its arguments unless you pass it by adress. so we
will have to either use uppercase names to indicate that we provide a
macro which does some really nasty magic to its arguments, or pass
the variables by adress. i'd much prefer the latter since even for
macros, i think arguments shouldn't be altered. i have to admit that
gtk in fact currently uses some macros that do this, but i carefully
kept them private to gtktypeutils.c (i'm talking about LOOKUP_TYPE_NODE),
and never intended to expose such things to the public API.
gtksignal.c used to use similar macros, but i later managed to do
LOOKUP_SIGNAL_ID() without argument modification.
so if we eventually decide to provide alloca() variants of e.g. strdup,
it should be something like:

#define g_alloca_strdup(string_p, source_string)  {
   gchar *s = source_string;
   gchar *p;
   p = alloca (strlen (s) + 1);
   *p = 0;
   strcpy (p, s);
   *string_p = p;
}

(plus all the other G_STMT* and NULL checking stuff).
i'm using an extra g_alloca_ prefix here because alloca() allocations are
pretty different from the normal malloc(3) based allocations (e.g. you can't
use alloca() during function call construction etc.. sopwith and kenneth gave
some good explainations on these things on gtk-devel-list), and people
should be aware of what they are doing. better lengthen the function/macro
names a bit than causing people to malloc-debug their programs all through
the next century.

> 
> Probably want a --disable-alloca, so that in combination with
> --enable-mem-check the programmer could sanity-check his alloca-based
> code.
> 
> Another idea:  it is would be easy to add primitive leak-checking to
> g_malloc and g_free, if another option --enable-mem-leak-check is added.
> In my mind this could dump the module/line number lists of allocations
> that were never free'd at the end of the program.

yeah, i've been thinking about that for some time as well, back in '97 when
i wrote GUBI i did some g_malloc/g_free replacements already that did record
allocations into a file and protected freed memory with mprotect(2) (linux
specific). something like that would be nice to have in glib directly, i've
just to find a free second to adapt that stuff (and probably advance it in
some areas).

> 
> 	Jeff
> 

jeff, this is an important topic, and providing a decent alloca() interface,
plus possible convenience macros is a non-trivial task, so i'd apprechiate
if you would forward this mail and eventual replies to gtk-devel-list.
especially since we already encountered valuable replies on this topic from
people on that list.

---
ciaoTJ




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