10 年前,使用 Gnome 库可能是有意义的,但现在它已成为遗留问题。 C89 可以说是世界上最标准的语言,具有非常稳定的特性和语法,因此调试别人的 C89 代码是可行的。
相比之下,Gnome 的 glib 在 C 标准之外更改了它的函数特性,因此您不仅可以调试由 C 制成的晦涩的包装器代码,而且您的代码可能会因为 Gnome 更改它的包装器函数而停止工作。
图表 A:g_snprintf()
标准 sprintf() 函数的一种更安全的形式。输出是
保证不超过 n 个字符(包括终止的 nul
字符),因此很容易确保缓冲区溢出不会
发生。
另见 g_strdup_printf()。
在 1.2.3 之前的 GLib 版本中,如果
输出被截断,截断的字符串可能不会
nul 终止。在 1.3.12 之前的版本中,此函数返回
输出字符串的长度。
g_snprintf()的返回值符合snprintf()函数
符合 ISO C99 标准。请注意,这不同于
传统的 snprintf(),它返回输出字符串的长度。
格式字符串可能包含位置参数,如
单一 Unix 规范。
我不太高兴能编写(又一个)链表来替换 Gnome 的,还有另一个版本的 snprintf() 和一堆蹩脚的包装代码,它们默默地占用 malloc() 的内存,从而破坏了C 编码的一个绝对最大值:“始终在同一范围内 malloc() 和 free()” 替换 g_strdup_printf()。
g_strdup_printf()
类似于标准 C sprintf() 函数,但更安全,因为它计算所需的最大空间并分配内存来保存结果。返回的字符串应该是
不再需要时使用 g_free() 释放。
加上在代码中进行大量字符串更改以执行“有用”的事情的快感,例如将 gchar 更改为 char、gint 到 int、gboolean 到 bool 等,等等,直到我的 Subversion 比较令人作呕现在是电话簿。更糟糕的是,您最终不得不更改越来越多的代码,因为这些东西散落在 .h 文件中,所以它会不断扩大,就像一具被划船的尸体,变成一团糟。
如果您正在确定一份合同工作的范围并在任何地方查看 glib.h,请运行!
就说不!
PS: 下载源代码,删除所有 Gnome 特定类型,然后重新编译它以使您自己的“g_”-less 函数有点工作,并且可以节省大量时间。
图表 B:g_strdup_printf()
来自 Gnome 的更可怕的 Gnome crappola。 Gnome 有很多“可爱”的函数,比如 g_strdup_vprintf(),它们“神奇地”知道你需要多少存储空间来保存返回的字符串,我有机会看看背后的“魔法”。这为我赢得了有史以来最可怕的 C 滥用奖。
如果你通过所有的包装函数继续追踪 g_strdup_vprintf(),你就会来到 gmessages.c 中的这个 gem....
/**
* 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;
}
不仅任何 printf() 函数在绝对为零时都比 snot 慢,您会注意到它们分配了整个字节,是的,整个 gchar c 用于存储,这保证了溢出,但是谁在乎呢?他们获得了 malloc() 所需的字符串的长度——因为他们将转身并再次执行整个 printf()——这一次,“神奇地”只有足够的存储空间。
当然,它们会在大小上加 1,因此您将有空间容纳一个 nul 终止符,当然,这肯定会付出可怕的代价,但他们已经把它隐藏在代码中的深处了打赌你会放弃并盲目使用它,而不会注意到这是多么大的脑放屁。啧啧,谢谢各位。我只是喜欢我的代码爬行。
不要让 _g_vsnprintf() 函数让你失望,因为在 gprintfint.h 中你会发现 little gem 只是普通老式 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__ */
强烈建议您在使用 Gnome 之前再次观看绿野仙踪,这样您就知道不要看幕后。欢迎来到我的噩梦!
任何认为 Gnome 比 C 更稳定的人都严重缺乏批判性思维。您可以用性能和透明度换取一些在 STL 中做得更好的好东西。