Re: GLib and 64-bit Windows



On Mon, 5 Mar 2007, Owen Taylor wrote:

On Mon, 2007-03-05 at 12:21 -0500, Jake Goulding wrote:

goption.c(994) : warning C4267: 'function' : conversion from 'size_t' to
'gulong', possible loss of data
change->allocated.array.data = g_renew (gchar *,
change->allocated.array.data, change->allocated.array.len + 2);

And more. It sure looks like most of them have to do with the allocation
functions, which all seem to take ulongs as opposed to size_t.

Hmm. I think in terms of gmem.h we probably should try to fix the
ulong/size_t situation. There is currently no ABI for GLib/Win64, so we
don't have to worry about a binary compatibility issue with changing the
prototype. And on all other platforms I know of gsize and ulong are the
same size.

agree. this exact API was actually written with sizeof(long)==8 on 64-bit
platforms in mind:

2008-01-29 14:58:31  Tim Janik  <timj imendio com>

        * glib/gmem.[hc]: changed size argument type from gulong to gsize as
        discussed on gtk-devel-list:
          http://mail.gnome.org/archives/gtk-devel-list/2007-March/msg00062.html
        this should be ABI compatible on all platforms except win64 for which
        no ABI binding port exists yet.

There *are* platforms where gssize is an unsigned integer rather than an
unsigned long, but my general feeling is that just changing the gmalloc
prototypes is unlikely to cause problems; GMemVTable, which would be
more likely to cause warnings already has gsize there.

i suppose you mean gsize (which is always unsigned), because gssize is
always signed.

There are going to be other situations however, where the fix isn't so
obvious.

- When 64-bit proofing the Unicode string bits of GLib (years ago)
  I took the policy that:

   - Counts of bytes were sized as gsize
   - Counts of "items" sized larger than a byte are longs

  because it seemed very strange to me to use size_t for non-byte
  counts.

C++ does this all the time though (also calls it's .get_number_of_elements()
methods .size()), so you get used to it after a bit of STL fiddling.

  But that means that something like the return value from
  g_utf8_strlen() is wrong for win32. This can't be changed in a
  source-compatible fashion.

  Probably the right thing to do for g_utf8_strlen() is to compute
  things internally as 64-bit, then clamp the result to 32-bits
  on return. Without the clamp:

    long size = g_utf8_strlen(str);
    gunichar chars = g_new(gunichar, size);
    for (char *p = str, gunichar *c = chars; *p; p = g_utf8_next_char(p)) {
   	  *c = g_utf8_get_char(p);
    }

   Is a potential buffer overflow, though a hard one to trigger.
   (Actually, it's a potential overflow currently for 32-bits. We really
   should make g_new0() not a g_malloc()-wrapping macro so we can protect
   the multiplication.)

if i understand you correctly, you mean to imply that we also fix the
signatures from *long to *size as well for the following functions
(comprehensive list of *long API in glib/glib/*.h):


gdouble  g_timer_elapsed         (GTimer      *timer,
                                  gulong      *microseconds);
void     g_usleep                (gulong       microseconds);
void     g_time_val_add          (GTimeVal    *time_,
                                  glong        microseconds);
gchar*   g_utf8_offset_to_pointer (const gchar *str,
                                   glong        offset) G_GNUC_PURE;
glong    g_utf8_pointer_to_offset (const gchar *str,
                                   const gchar *pos) G_GNUC_PURE;
glong g_utf8_strlen (const gchar *p,
                     gssize       max) G_GNUC_PURE;
gunichar2 *g_utf8_to_utf16     (const gchar      *str,
                                glong             len,
                                glong            *items_read,
                                glong            *items_written,
                                GError          **error) G_GNUC_MALLOC;
gunichar * g_utf8_to_ucs4      (const gchar      *str,
                                glong             len,
                                glong            *items_read,
                                glong            *items_written,
                                GError          **error) G_GNUC_MALLOC;
gunichar * g_utf8_to_ucs4_fast (const gchar      *str,
                                glong             len,
glong *items_written) G_GNUC_MALLOC; gunichar * g_utf16_to_ucs4 (const gunichar2 *str,
                                glong             len,
                                glong            *items_read,
                                glong            *items_written,
                                GError          **error) G_GNUC_MALLOC;
gchar*     g_utf16_to_utf8     (const gunichar2  *str,
                                glong             len,
                                glong            *items_read,
                                glong            *items_written,
                                GError          **error) G_GNUC_MALLOC;
gunichar2 *g_ucs4_to_utf16     (const gunichar   *str,
                                glong             len,
                                glong            *items_read,
                                glong            *items_written,
                                GError          **error) G_GNUC_MALLOC;
gchar*     g_ucs4_to_utf8      (const gunichar   *str,
                                glong             len,
                                glong            *items_read,
                                glong            *items_written,
                                GError          **error) G_GNUC_MALLOC;
gboolean g_hook_destroy                 (GHookList              *hook_list,
                                         gulong                  hook_id);
GHook*   g_hook_get                     (GHookList              *hook_list,
                                         gulong                  hook_id);
gint                  g_snprintf           (gchar       *string,
                                            gulong       n,
                                            gchar const *format,
                                            ...) G_GNUC_PRINTF (3, 4);
gint                  g_vsnprintf          (gchar       *string,
                                            gulong       n,
                                            gchar const *format,
                                            va_list      args);
GThread* g_thread_create_full  (GThreadFunc            func,
                                gpointer               data,
                                gulong                 stack_size,
                                gboolean               joinable,
                                gboolean               bound,
                                GThreadPriority        priority,
                                GError               **error);
struct _GThreadFunctions
{
  void      (*thread_create)      (GThreadFunc           func,
                                   gpointer              data,
                                   gulong                stack_size,
                                   gboolean              joinable,
                                   gboolean              bound,
                                   GThreadPriority       priority,
                                   gpointer              thread,
                                   GError              **error);
};
G_INLINE_FUNC gint      g_bit_nth_lsf (gulong  mask,
                                       gint    nth_bit) G_GNUC_CONST;
G_INLINE_FUNC gint      g_bit_nth_msf (gulong  mask,
                                       gint    nth_bit) G_GNUC_CONST;
G_INLINE_FUNC guint     g_bit_storage (gulong  number) G_GNUC_CONST;


what about GTimeVal?

struct _GTimeVal
{
  glong tv_sec;
  glong tv_usec;
};

does struct timeval use 32 or 64 bit fields on win64?

   Things like this need to be handled case-by-case. (And not all of them
   are going to generate warnings! I don't think you'll get any warnings
   from g_utf8_strlen())

from what i can see, moving *long to *size for the above API (also
some exposed GHook/GScanner structures) shouldn't be a problem,
dunno about GTimeVal though.

- There will be some cases where you'll get warnings where it is
  obvious from the code that there is no problem. Adding casts
  to suppress the warnings there should be fine.

					- Owen

---
ciaoTJ


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