运行 GLib 应用程序
运行 GLib 应用程序
环境变量
GLib 应用程序的运行时行为可受若干环境变量的影响。
- 标准变量
- GLib 读取诸如
LANG
、PATH
、HOME
、TMPDIR
、TZ
和LOGNAME
的标准环境变量。 - XDG 目录
- GLib 查阅环境变量
XDG_DATA_HOME
、XDG_DATA_DIRS
、XDG_CONFIG_HOME
、XDG_CONFIG_DIRS
、XDG_CACHE_HOME
和XDG_RUNTIME_DIR
以获取各种 XDG 目录。有关详细信息,请参阅 XDG 基本目录规范。 G_FILENAME_ENCODING
- 此环境变量可设置为字符集名称的逗号分隔列表。GLib 假设文件名编码在该列表中的第一个字符集中,而不是 UTF-8 中。特殊标记“
locale
”可用于指定当前区域设置的字符集。 G_BROKEN_FILENAMES
- 如果设置此环境变量,GLib 假设文件名采用区域设置编码,而不是 UTF-8。
G_FILENAME_ENCODING
优先于G_BROKEN_FILENAMES
。 G_MESSAGES_PREFIXED
- 日志级别列表,其中消息应以应用程序的程序名称和 PID 作为前缀。默认值为除了
G_LOG_LEVEL_MESSAGE
和G_LOG_LEVEL_INFO
之外对所有内容添加前缀。可能的值包括:error、warning、critical、message、info 和 debug。你还可以使用特殊值 all 和 help。此环境变量只影响默认日志处理程序g_log_default_handler()
。 G_MESSAGES_DEBUG
- 日志域的空间分隔列表,其中应打印信息和调试消息。默认情况下,不打印这些消息。你还可以使用特殊值 all。此环境变量只影响默认日志处理程序
g_log_default_handler()
。 G_DEBUG
- 此环境变量可设置为调试选项列表,这会导致 GLib 打印出不同类型的调试信息。
fatal-warnings
:导致 GLib 在第一次调用g_warning()
或g_critical()
时中止程序。建议不要使用此标志,除非在进行调试时。fatal-criticals
:导致 GLib 在第一次调用g_critical()
时中止程序。在进行调试和测试期间,此标志可能很有用。gc-friendly
:直接初始化的新分配的内存以及要释放的内存将被重置为 0。这里的要点是让内存检查程序和类似于博姆 GC 算法的其他程序生成更准确的结果。resident-modules
:GModule 加载的所有模块都将变为永久驻留的。这可能有助于跟踪稍后会卸载的模块中的内存泄漏;但它还可能隐藏在模块正常卸载后访问代码的错误。bind-now-modules
:GModule 加载的所有模块都会在加载时绑定其符号,即使代码使用G_MODULE_BIND_LAZY
也是如此。
特殊值 all
可用于启用所有调试选项。特殊值 help
可用于打印所有可用选项。
G_SLICE
- 此环境变量允许重新配置 GSlice 内存分配器。自 GLib 2.76 以来,GSlice 在内部使用系统
malloc()
实现,因此此变量将被忽略。 G_RANDOM_VERSION
- 如果将此环境变量设置为“2.0”,则 GLib 2.0 的已过时的伪随机数种子和生成算法将代替较新、更好的算法使用。如果您需要生成精确复制使用 Glib 2.0 生成的数字序列,则应设置此变量。
LIBCHARSET_ALIAS_DIR
- 允许为字符集转换例程使用的 `charset.aliases` 文件指定非标准位置。默认位置是在编译时指定的 `libdir`。
TZDIR
- 允许为 `GDateTime` API 使用的时区数据文件指定非标准位置。默认位置在 `/usr/share/zoneinfo` 下。有关更多信息,另请参见 `tzset` 手册页。
G_ENABLE_DIAGNOSTIC
- 如果设置为非零值,则此环境变量启用诊断消息,例如 GObject 属性和信号的弃用消息。
G_DEBUGGER
- 在 Windows 上运行时,如果设置为非空字符串,则 GLib 将尝试将此环境变量的内容解释为调试器的命令行,并在进程崩溃时运行它。调试器命令行应包含 `%p` 和 `%e` 替换令牌,GLib 将其替换为崩溃进程的进程 ID 和调试器应发出信号以让 GLib 了解调试器已成功附加到进程的事件句柄。如果 `%e` 不存在,或者调试器无法发出事件信号,则 GLib 将在 60 秒后恢复执行。如果 `%p` 不存在,则调试器将不知道附加到哪个进程,GLib 也会在 60 秒后恢复执行。此外,即使未设置 `G_DEBUGGER`,GLib 仍会尝试将基本异常信息(代码和地址)打印到 `stderr` 中。默认情况下,调试器会为其分配一个新的控制台。将 `G_DEBUGGER_OLD_CONSOLE` 环境变量设置为任何非空字符串,以使调试器继承崩溃进程的控制台。通常只有 GLib 测试套件使用此功能。异常处理程序的编写旨在尽可能简单,以最大程度地降低调用错误功能或运行错误代码的风险,这将导致异常递归引发。正因如此,它缺少 GLib 预期的大多数便利设施。也就是说,它不支持 Unicode,因此强烈建议仅在 `G_DEBUGGER` 中使用 ASCII 字符。另请参见 `G_VEH_CATCH`。
G_VEH_CATCH
- 捕获某些异常可能会中断程序,因为 Windows 有时会将异常用于执行流控制和其他除发出崩溃信号之外的目的。`G_VEH_CATCH` 环境变量扩充了 Windows 上的向量化异常处理(请参阅 `G_DEBUGGER`),允许 GLib 捕获更多异常。将此变量设置为应另外捕获的已分隔十六进制异常代码的逗号分隔列表。默认情况下,GLib 将仅捕获访问冲突、堆栈溢出和非法指令异常。
语言环境
GLib 中的许多接口取决于应用程序运行时的当前语言环境。因此,大多数使用 GLib 的应用程序应调用 `setlocale (LC_ALL, "")` 来设置当前语言环境。
在 Windows 上,C 程序中有多个语言环境概念未必会同步。一方面,有系统默认的 ANSI 代码页,它决定 C 库函数和 Win32 API 处理的文件名使用哪种编码。(我们这里讨论的是使用字符指针的“窄”函数,而不是“宽”函数。)
另一方面,还有 C 库当前区域设置。它所使用的字符集(代码页)不一定与系统默认的 ANSI 代码页相同。字符串在此字符集中由 strftime()
等函数返回。
使用 GDB 进行调试
GLib 随一组 Python 宏一同提供,适用于 GDB 调试器。这些宏可以简化使用 GLib 编写的应用程序的调试。
若要使用此功能,您需要在与 GDB 相同的前缀中安装 GLib,以便 Python GDB 自动加载的文件安装在 GDB 正确挑选的地方。
您可以在 gdb 会话中运行以下命令,检查 gdb 是否正确挑选了 GLib gdb 脚本。
(gdb) info auto-load python-scripts
Loaded Script
Yes /usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.7800.0-gdb.py
Yes /usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.7800.0-gdb.py
版本号和路径可能因 OS 发行版本而异,但如果您看到为 libglib 和 libgobject 列出的条目,那么 gdb 脚本应该会正常工作。
在使用 GLib 编写的应用程序进行调试时,GLib Python 宏提供以下好处。
- 以美观的方式打印 GLib 类型
- 使用
gforeach
命令迭代列表 - 回溯修饰
1. 以美观的方式打印 GLib 类型:
一般性的以美观的方式打印 GLib 类型应该无需执行任何特殊操作即可正常工作。
例如,打印带有字符串键的哈希表将按照以下格式显示哈希内容。
(gdb) print my_string_hash_variable
$1 = 0x5555556d9660 = {
[0x7ffff76f6592 "GdkWaylandPopup"] = 0x555555768a50,
[0x7ffff76e67e8 "GtkStyleProvider"] = 0x5555557a19c0,
[0x7ffff7db7151 "GHttpProxy"] = 0x5555556f5bc0
}
打印带有指针键的哈希表将按照以下格式显示哈希内容。
(gdb) print my_pointer_hash_variable
$2 = 0x5555556dcb50 = {
[0x555555b59ec0] = 0x555555b59770,
[0x555555c79f80] = 0x555555c86b00,
[0x555555c68f40] = 0x555555c69630
}
打印列表将按照以下格式显示列表内容。
(gdb) p my_appname_list
$3 = 0x55c4582deef0 = {0x7f16ab85dc90, 0x7f16abb02700, 0x7f16a80066e0}
即使列表有字符串条目,我们也不可能对字符串条目进行解码和打印,因为 GLib 在内部将列表条目存储为 gpointer
。不过,可以使用 gforeach
命令实现上述目的。
2. 使用“gforeach”命令迭代列表:
gforeach
命令可以用于对列表(GList
/GSList
)中的每个条目应用命令。我们还可以将列表中的 gpointer
类型转换为所需类型。
例如,要打印名为 my_appname_list
的字符串列表中的所有字符串,可以执行以下操作。
(gdb) gforeach appname in my_appname_list: print (gchar*) $appname
$4 = (gchar *) 0x7f16ab85dc90 "Boxes"
$5 = (gchar *) 0x7f16abb02700 "GNOME Application Platform version 45"
$6 = (gchar *) 0x7f16a80066e0 "Firefox ESR"
您还可以在列表中的每个条目上调用函数,如下所示
(gdb) gforeach appname in my_appname_list: call (int) strlen($appname)
$7 = 5
$8 = 37
$9 = 11
3. 回溯修饰:
回溯会使用 GLib 类型名称和信号名称进行修饰。
例如,从以下回溯中我们可以看出,当一个按钮(通过 GtkButton
类型修饰)被单击(通过 clicked
信号修饰)时调用了 gs_updates_page_button_refresh_cb ()
回调函数。
#0 gs_updates_page_button_refresh_cb (widget=0x5602f986b670 [GtkButton], self=0x5602f93aeb80 [GsUpdatesPage]) at ../src/gs-updates-page.c:826
#1 0x00007f09da7651de in <emit signal 'clicked' on instance 0x5602f986b670 [GtkButton]> (instance=0x5602f986b670, signal_id=158, detail=0) at ../gobject/gsignal.c:3675
#2 0x00007f09da747bad in g_cclosure_marshal_VOID__VOIDv (closure=0x5602f986c6a0, return_value=0x0, instance=0x5602f986b670, ...)
at ../gobject/gmarshal.c:165
…
#20 0x00007f09da52c250 in g_application_run (application=0x5602f9068ae0 [GsApplication], argc=1, argv=0x7ffcfb3bb468) at ../gio/gapplication.c:2577
#21 0x00005602f8b53ccd in main (argc=1, argv=0x7ffcfb3bb468) at ../src/gs-main.c:49
以下是没有任何 GLib 修饰的相同回溯,它不是很实用。
#0 gs_updates_page_button_refresh_cb (widget=0x5602f986b670, self=0x5602f93aeb80) at ../src/gs-updates-page.c:826
#1 0x00007f09da747bad in g_cclosure_marshal_VOID__VOIDv (closure=0x5602f986c6a0, return_value=0x0, instance=0x5602f986b670, ...)
at ../gobject/gmarshal.c:165
…
#20 0x00007f09da52c250 in g_application_run (application=0x5602f9068ae0, argc=1, argv=0x7ffcfb3bb468) at ../gio/gapplication.c:2577
#21 0x00005602f8b53ccd in main (argc=1, argv=0x7ffcfb3bb468) at ../src/gs-main.c:49
SystemTap
SystemTap 是一种动态的整个系统分析工具包。GLib 随文件 libglib-2.0.so.*.stp
一起提供,该文件定义了一组探测点,您可以使用自定义 SystemTap 脚本挂接到这些探测点。请参阅您共享的 SystemTap 脚本目录中的文件 libglib-2.0.so.*.stp
、libgobject-2.0.so.*.stp
和 libgio-2.0.so.*.stp
。
内存统计信息
如果已通过调用启用内存分析,则 g_mem_profile()
将输出摘要 g_malloc()
内存使用情况
g_mem_set_vtable (glib_mem_profiler_table);
在启动时。
如果 GLib 已配置为具有完整调试支持,则可以在调试器中调用 g_slice_debug_tree_statistics()
以输出有关切片分配器内存使用情况的详细信息。