Re: GLib and 64-bit Windows
- From: Tim Janik <timj imendio com>
- To: Owen Taylor <otaylor redhat com>
- Cc: GTK Devel List <gtk-devel-list gnome org>
- Subject: Re: GLib and 64-bit Windows
- Date: Tue, 29 Jan 2008 15:12:29 +0100 (CET)
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]