使用C和GTK +进行编程时,为什么使用g_strdup_printf
,g_free
,g_strcmp0
等以及其他GLib函数会“更好”?
答案 0 :(得分:27)
通常,GLib的目的是实用程序和可移植性库。这些本身就是考虑使用它的理由。
您提到的特定功能都提供了额外的C标准库变体:
g_strdup_printf
与sprintf
类似,但实际上为您分配了缓冲区,并省去了对缓冲区应该有多大的猜测。 (返回值应为g_free
'd。)g_free
与free
类似,但会检查NULL指针。g_strcmp0
与strcmp
类似,但将NULL指针视为空字符串,因此将其排在前面。答案 1 :(得分:7)
用于多个操作系统中的一致行为。这是一种便携性的东西。
在除Linux之外的其他一些unix环境中,或者如果您的程序是在Windows上编译的,其中一些功能可能在目标操作系统上不存在或行为不同。
使用glib版本可确保一致的行为。
答案 2 :(得分:4)
他们的行为在GTK +支持的任何平台上都有明确定义,而本机功能可能有时会在中途工作。
答案 3 :(得分:3)
我不得不说,这很有意义,但执行得不好。当你尝试多次释放()一个指针时,你的程序不会崩溃和刻录是很好的。或者对NULL字符串进行排序。但那是一种喜忧参半的祝福。它可以防止您在代码中发现这些令人讨厌的错误。有一天你不仅很难将你的程序移植,因为你依赖非标准功能,你会有一个真的困难时间,因为你的代码是错误的,你从来没有找到过进行。
答案 4 :(得分:3)
GLib提供了可移植性和当前任何编程语言所期望的基本功能,如集合类型(链表,数组,哈希表等)。以下是GLib可以为您提供的一些好处。
<强>可移植性强>
GLib的要点是可移植而不是C标准,而是标准的实现。 GLib处理了一开始可能看起来毫无用处的已知怪癖,直到您需要将代码移植到具有那些令人讨厌的错误的平台上。
让我们以g_free
为例,许多人批评它。 There are platforms where free(NULL)
will fail,即使C99说它应该有效。该检查至少存在于1998年(我在git历史中跟踪它)。有些人可能会说它不再需要了,但即使在2017年,我在一家公司工作,在调用NULL
之前检查free
,否则它会在他们的嵌入式平台上崩溃。当你想要进行一些严肃的内存调试时,它还可以作为代码入侵的包装器。
<强>可读性强>
它通过提供一些包装函数来帮助提高代码的可读性,这些函数不仅可以提高portabitlity,还可以帮助您避免许多语言陷阱。有多少人测试malloc
以查看它是否返回NULL
?如果它返回NULL
,你有多少人有办法恢复,因为你基本没有内存?
g_malloc
将中止该应用程序,在许多应用程序中,这只是您想要的行为。对于可能失败的非常大的分配,您有g_try_malloc
。这与malloc相同,但仍然为您提供了可用于检测的包装器的好处。
能够写作:
char *buffer = g_malloc(30);
/* Do something with it ... */
g_free (buffer);
......释放思绪,让开发人员专注于她想要实现的任务。它还可以避免程序崩溃,因为它尝试使用NULL
指针进行编写,并且您必须跟踪分配。
标准C库充满了陷阱,无需微观管理您编写的每一行代码都是一种解脱。只需阅读联机帮助页面的 BUGS 部分,了解一些功能,您就会看到。使用较少的样板代码来检查错误会使代码更易于阅读,从而提高可维护性并减少错误。
功能强>
另一点是GLib提供的整套收集类型,您不必重新实现。仅仅因为重新实现链表很容易并不意味着你应该这样做。我在另一家公司工作,该公司提供了几个链接列表实现的代码,因为一些开发人员只会拥有 Not Invented Here 综合症,并会重新开发自己的。一个普遍的,经过彻底测试的广泛的库,如GLib,有助于避免这种无稽之谈。除非你有非常具体的性能限制,否则你不应该重新开发这些东西。
答案 5 :(得分:-2)
相比之下,Gnome的glib更改了C标准以外的函数功能,因此您不仅可以处理调试由C构成的模糊包装代码,而且您的代码可能会停止工作,因为Gnome更改了它的包装函数。
图表A:g_snprintf()
标准sprintf()函数的更安全形式。输出是 保证不超过n个字符(包括终止nul 字符),因此很容易确保缓冲区溢出不能 发生。
另见g_strdup_printf()。
在1.2.3之前的GLib版本中,如果是,则此函数可能返回-1 输出被截断,截断的字符串可能不是 空终止。在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 _” - 减少函数sorta,有点工作,并且节省大量时间。
图表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的大小,所以你有足够的空间来保证,当然可怕的费用,但他们已经把它隐藏在代码中如此之深打赌你只是放弃并盲目地使用它,而不是注意到这是一个巨大的脑屁。哎呀,谢谢你们。我只是喜欢我的代码来抓取。
不要让_g_vsnprintf()函数抛弃你,因为在gprintfint.h中你会发现小宝石只是普通老香草的另一个名字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中做得更好的一些好东西。
答案 6 :(得分:-4)
这是一个更新。看起来开发人员意识到他们的错误:
g_mem_is_system_malloc自版本2.46起已被弃用,不应在新编写的代码中使用。
GLib始终使用系统malloc,因此该函数始终返回TRUE。
检查g_malloc()使用的分配器是否是系统的malloc实现。如果返回TRUE,则使用malloc()分配的内存可与使用g_malloc()分配的内存互换。此函数对于避免非基于GLib的API返回的已分配内存的额外副本非常有用。
https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html#g-mem-is-system-malloc