Why use GLib functions?

后端 未结 7 528
野的像风
野的像风 2021-01-31 17:30

While programming in C and GTK+, why is it \"better\" to use g_strdup_printf, g_free, g_strcmp0 etc... and fellow GLib functions?

7条回答
  •  醉梦人生
    2021-01-31 17:55

    10 years ago, using the Gnome lib may have made sense, but its now a legacy liability. C89 is arguably the most standard language in the world, with very stable features and syntax, so debugging someone else's C89 code is doable.

    By contrast Gnome's glib changes it's function's features outside of the C Standard, so not only do you get to deal with debugging obscure wrapper code made of C, but your code may stop working because Gnome changes it's wrapper functions.

    Exhibit A: g_snprintf()

    A safer form of the standard sprintf() function. The output is guaranteed to not exceed n characters (including the terminating nul character), so it is easy to ensure that a buffer overflow cannot occur.

    See also g_strdup_printf().

    In versions of GLib prior to 1.2.3, this function may return -1 if the output was truncated, and the truncated string may not be nul-terminated. In versions prior to 1.3.12, this function returns the length of the output string.

    The return value of g_snprintf() conforms to the snprintf() function as standardized in ISO C99. Note that this is different from traditional snprintf(), which returns the length of the output string.

    The format string may contain positional parameters, as specified in the Single Unix Specification.

    I'm less than thrilled I get to write (yet another) linked-list to replace Gnome's, AND yet another version of snprintf() and a bunch of crappy wrapper code that silently malloc()s memory, thereby breaking the one absolute maxium of C coding: "Always malloc() and free() in the same scope" to replace g_strdup_printf().

    g_strdup_printf ()

    Similar to the standard C sprintf() function but safer, since it calculates the maximum space required and allocates memory to hold the result. The returned string should be freed with g_free() when no longer needed.

    Add to this the thrill of making massive numbers of string changes in the code to do "useful" things like change gchar to char, gint to int, gboolean to bool, etc, etc, etc, ad nauseam until my Subversion comparisons are now a phone book. Worse, you end up having to change more and more code because this stuff is littered all over the .h files, so it keeps expanding, like a boated corpse, into a huge mess.

    If you're scoping a contract job and see glib.h anywhere, RUN!!! Just say NO!.

    PS: Downloading the source, removing all the Gnome-specific types, and recompiling it to make your own "g_"-less functions sorta, kinda works, and is a big time-saver.

    Exhibit B: g_strdup_printf()

    More horrific Gnome crappola from Gnome. Gnome has lots of "lovely" functions like g_strdup_vprintf() that "magically" know how much storage you need to hold your returned string, and I had occasion to look behind the "magic". This wins my award for the most hideous abuse of C ever.

    If you keep tracing g_strdup_vprintf() back through all the wrapper functions, you come to this gem in gmessages.c....

    /**
     * g_printf_string_upper_bound:
     * @format: the format string. See the printf() documentation
     * @args: the parameters to be inserted into the format string
     *
     * Calculates the maximum space needed to store the output
     * of the sprintf() function.
     *
     * Returns: the maximum space needed to store the formatted string
     */
    gsize
    g_printf_string_upper_bound (const gchar *format,
                                 va_list      args)
    {
      gchar c;
      return _g_vsnprintf (&c, 1, format, args) + 1;
    }
    

    Not only is ANY printf() function slower than snot at absolute zero, you'll notice they allocate an entire byte, yup, a whole gchar c, for storage, which guarantees overflow, but then who cares? they get the length of the string they'll need to malloc() - because they are going to turn around and do the whole printf() over again - this time, "magically" with just enough storage.

    They'll add +1 to the size, of course, so you'll have room for a nul-terminator, guaranteed, at horrific expense of course, but they've hid it so deep in the code they're betting you'll just give up and use it blindly and not notice what a massive brain-fart this is. Gee, thanks guys. I just love my code to crawl.

    Don't let the _g_vsnprintf() function throw you off, because in gprintfint.h you'll discover that little gem is just another name for plain old vanilla vsnprintf();

    /* GLIB - Library of useful routines for C programming
     * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2 of the License, or (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with this library; if not, write to the
     * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     * Boston, MA 02111-1307, USA.
     */
    
    /*
     * Modified by the GLib Team and others 2002.  See the AUTHORS
     * file for a list of people on the GLib Team.  See the ChangeLog
     * files for a list of changes.  These files are distributed with
     * GLib at ftp://ftp.gtk.org/pub/gtk/. 
     */
    
    #ifndef __G_PRINTFINT_H__
    #define __G_PRINTFINT_H__
    
    #ifdef HAVE_GOOD_PRINTF
    
    #define _g_printf    printf
    #define _g_fprintf   fprintf
    #define _g_sprintf   sprintf
    #define _g_snprintf  snprintf
    
    #define _g_vprintf   vprintf
    #define _g_vfprintf  vfprintf
    #define _g_vsprintf  vsprintf
    #define _g_vsnprintf vsnprintf
    
    #else
    
    #include "gnulib/printf.h"
    
    #define _g_printf    _g_gnulib_printf
    #define _g_fprintf   _g_gnulib_fprintf
    #define _g_sprintf   _g_gnulib_sprintf
    #define _g_snprintf  _g_gnulib_snprintf
    
    #define _g_vprintf   _g_gnulib_vprintf
    #define _g_vfprintf  _g_gnulib_vfprintf
    #define _g_vsprintf  _g_gnulib_vsprintf
    #define _g_vsnprintf _g_gnulib_vsnprintf
    
    #endif
    
    #endif /* __G_PRINTF_H__ */
    

    It's highly recommended that you watch the Wizard Of Oz again before working with Gnome, so you'll know not to look behind the curtain. Welcome to my nightmare!

    Anyone that thinks Gnome is more stable than C is badly lacking in critical thinking. You trade performance and transparency for a few nice things that are done better in the STL.

提交回复
热议问题