Зачем использовать функции GLib? - PullRequest
28 голосов
/ 10 февраля 2010

При программировании на C и GTK +, почему "лучше" использовать g_strdup_printf, g_free, g_strcmp0 и т. Д ... и другие функции GLib?

Ответы [ 7 ]

27 голосов
/ 10 февраля 2010

В общем, целью GLib является библиотека утилит и переносимости. Это само по себе является причиной, чтобы рассмотреть возможность его использования.

Специальные функции, о которых вы упомянули, предлагают что-то дополнительное в дополнение к их вариантам стандартной библиотеки C:

  • g_strdup_printf похоже на sprintf, но фактически выделяет буфер для вас и избавляет вас от догадок о том, насколько большим должен быть буфер. (Возвращаемое значение должно быть g_free 'd.)
  • g_free похож на free, но проверяет NULL-указатель.
  • g_strcmp0 похож на strcmp, но обрабатывает NULL-указатель как пустую строку и, таким образом, сортирует его впереди.
7 голосов
/ 10 февраля 2010

Для согласованного поведения в нескольких операционных системах. Это портативность.

В некоторых других средах Unix, кроме Linux, или если ваша программа скомпилирована в Windows, некоторые из этих функций могут не существовать или работать в целевой операционной системе иначе.

Использование версий glib обеспечивает согласованное поведение.

4 голосов
/ 10 февраля 2010

Их поведение четко определено на любой платформе, поддерживаемой GTK +, в отличие от собственных функций, которые иногда могут работать частично.

3 голосов
/ 14 декабря 2017

GLib обеспечивает переносимость и базовые возможности, которые вы ожидаете в настоящее время от любого языка программирования, такие как типы коллекций (связанные списки, массивы, хеш-таблицы и т. Д.). Вот некоторые из преимуществ, которые GLib может дать вам.

Портативность


Смысл GLib в том, чтобы быть переносимым не к стандарту C, а к реализациям стандарта. GLib позаботится об известных причудах, которые на первый взгляд могут показаться бесполезными, пока вам не понадобится перенести свой код на платформу с такими неприятными ошибками.

Давайте возьмем пример g_free, как многие его критикуют. Существуют платформы, на которых free(NULL) не удастся , даже если C99 говорит, что он должен работать. Эта проверка существует как минимум с 1998 года (я отслеживал ее в истории git). Некоторые могут сказать, что это больше не нужно, но даже в 2017 году я работал в компании, которая проверяет NULL перед вызовом free, потому что в противном случае это могло бы привести к падению на их встроенной платформе. Он также служит оболочкой для внедрения вашего кода, когда вы хотите выполнить серьезную отладку памяти.

читаемость


Это помогает улучшить читабельность вашего кода, предоставляя некоторые функции-обертки, которые не только улучшают переносимость, но и помогают избежать многих языковых ошибок. Кто из вас проверяет malloc, чтобы узнать, вернется ли он NULL? У кого из вас есть способ восстановиться, если он вернет NULL, так как у вас в основном недостаточно памяти?

g_malloc будет прерывать приложение, если оно не может выделить то, что вам нужно, и во многих приложениях это именно то поведение, которое вам нужно. Для очень больших выделений, которые могут потерпеть неудачу, у вас есть g_try_malloc. Это то же самое, что и malloc, но, тем не менее, дает вам преимущество в качестве обертки, которую можно использовать для инструментовки.

Возможность написать:

char *buffer = g_malloc(30);
/* Do something with it ... */
g_free (buffer);

... освобождает разум и позволяет разработчику сосредоточиться на задаче, которую она пытается достичь. Это также позволяет избежать сбоя вашей программы намного позже, потому что она пытается писать, используя указатель NULL, и вы должны отслеживать распределение.

Стандартная библиотека C полна ловушек, и отсутствие микроуправления каждой строкой кода, которую вы пишете, является облегчением. Просто прочитайте раздел BUGS на страницах man для некоторых функций, и вы увидите. Наличие меньшего количества стандартного кода для проверки ошибок делает код более простым для чтения, что повышает удобство сопровождения и вызывает меньше ошибок.

Особенности


Еще один момент - целая куча типов коллекций, которые предоставляет GLib, и что вам не нужно переопределять. То, что переопределение связанного списка легко, не означает, что вы должны это делать. Я работал в другой компании, которая поставляла код с несколькими реализациями связанных списков, потому что некоторые разработчики просто имели бы синдром Not Invented Here и перерабатывали свои собственные. Обычная, тщательно проверенная, широко распространенная библиотека, такая как GLib, помогает избежать этой чепухи. Вы не должны перестраивать этот материал, если у вас нет особых ограничений производительности.

3 голосов
/ 11 февраля 2010

Я должен сказать, что это хорошо задумано, но не очень хорошо выполнено. Приятно, что ваша программа не будет аварийно завершать работу, если вы попытаетесь освободить () указатель более одного раза. Или сортируйте пустую строку. Но это смешанное благословение. Он также не позволяет вам обнаружить эти неприятные ошибки в вашем коде. Вам не только будет трудно портировать вашу программу однажды, потому что вы полагаетесь на нестандартные функции, у вас будет действительно трудное время, потому что ваш код содержит ошибки и вы никогда не узнаете .

0 голосов
/ 24 ноября 2015

Вот обновление. Похоже, разработчик понял свою ошибку:

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

0 голосов
/ 29 января 2014

10 лет назад использование библиотеки Gnome, возможно, имело смысл, но теперь это наследство. C89, пожалуй, самый стандартный язык в мире, с очень стабильными функциями и синтаксисом, поэтому отладка чужого кода C89 выполнима.

В отличие от glib Gnome изменяет функции своей функции вне стандарта C, так что вы не только сталкиваетесь с отладкой неясного кода-обертки, созданного на C, но и ваш код может перестать работать, потому что Gnome меняет свои функции-обертки.

Приложение A: g_snprintf ()

Более безопасная форма стандартной функции sprintf (). Выход гарантированно не должен превышать n символов (включая завершающий ноль символ), поэтому легко убедиться, что переполнение буфера не может происходят.

См. Также g_strdup_printf ().

В версиях GLib до 1.2.3 эта функция может возвращать -1, если вывод был усечен, а усеченная строка не может быть NUL-прекращается. В версиях до 1.3.12 эта функция возвращает длина выходной строки.

Возвращаемое значение g_snprintf () соответствует функции snprintf () как стандартизировано в ISO C99. Обратите внимание, что это отличается от традиционный snprintf (), который возвращает длину выходной строки.

Строка формата может содержать позиционные параметры, как указано в Спецификация Single 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 _", вроде как, работает и очень экономит время.

Приложение B: g_strdup_printf ()

Более ужасный гном-краппола из Гнома. В Gnome есть множество «прекрасных» функций, таких как g_strdup_vprintf (), которые «волшебным образом» знают, сколько памяти нужно для хранения возвращаемой строки, и у меня была возможность заглянуть за «магию». Это выигрывает мою награду за самое отвратительное злоупотребление С когда-либо.

Если вы продолжаете отслеживать g_strdup_vprintf () через все функции-оболочки, вы попадаете в этот гем в 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;
}

ЛЮБАЯ функция printf () не только медленнее, чем сопли при абсолютном нуле, вы заметите, что они выделяют для хранения целый байт, да, целый gchar c, что гарантирует переполнение, но тогда кого это волнует? они получают длину строки, которая им понадобится для malloc () - потому что они собираются развернуться и снова выполнить весь printf () - на этот раз «волшебным образом» с достаточным объемом памяти.

Они, конечно, добавят +1 к размеру, так что у вас будет место для nul-терминатора, гарантировано, конечно, за ужасную цену, но они спрятали это так глубоко в коде, что держу пари, что вы просто сдадитесь и будете использовать его вслепую и не заметите, что это за огромный пердеж. Ну и дела, спасибо, ребята. Я просто люблю свой код для сканирования.

Не позволяйте функции _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.

...