编写 GLib 应用程序

编写 GLib 应用程序

内存分配

除非另行指定,所有在 GLib 中分配内存的函数,在堆分配失败时终止进程。这是因为在任何非平凡的程序中,从分配失败中恢复过来都太困难,特别是,测试所有可能的分配失败代码路径。

UTF-8 和字符串编码

除非另行指定,所有 GLib、GObject 和 GIO 函数接受并返回 UTF-8 编码 的字符串。

对于函数调用的输入字符串,不会 检查它们是否是有效的 UTF-8:在输入字符串时由应用程序开发者负责验证输入字符串,在程序或库边界,并且,仅在它们应用程序中使用有效的 UTF-8 字符串常量。如果 GLib 要对所有函数的所有字符串输入执行 UTF-8 验证,则会显著降低性能。

类似地,从函数调用的输出字符串保证为 UTF-8 编码,并且不需要调用函数进行验证。如果一个函数返回无效的 UTF-8 编码(并且没有说明它这么做),则这是一个 bug。

请参阅 g_utf8_validate()g_utf8_make_valid() 以了解如何验证 UTF-8 输入。

线程

GLib 的通用策略是,所有函数在无形中都是线程安全的,除了数据结构处理函数,如果你有两个处理相同数据结构的线程,它们必须使用锁来同步它们的运算。

GLib 创建了一个工作程序线程用于它自己的目的,所以 GLib 应用程序总是至少有 2 个线程。

特别是,这意味着程序必须仅使用 异步信号安全函数 在调用 fork()exec() 之间,即使尚未明确生成另一个线程。

请参阅有关 线程GThreadPool 的章节,了解支持多线程应用程序的 GLib API。

安全性与 setuid 使用

在编写具有提升权限运行的代码时,遵循某些安全编程基本规则非常重要。David Wheeler 在此主题方面写了一本极好的书,Linux 和 Unix HOWTO 安全编程

当涉及到 GLib 及其关联的库时,一般来说在具有提升权限运行的代码中使用 GLib 和 GObject 是没有问题的;它们不会在“你的身后”加载模块(共享对象中的可执行代码)或运行其他程序。然而,GIO 不适用于在特权程序中使用,特权程序既可能是由特权进程产生的,也可能是带有设置的 setuid 位运行的。

setuid 程序应该在调用 GIO 等非平凡库之前始终重置它们的环境,以仅包含已知安全的值。这降低了攻击者控制的环境变量被用来通过加载 GIO 模块或类似方式获取特权 GIO 进程以运行任意代码的风险。