Talloc

本文介绍了talloc,一种用于简化复杂数据结构内存管理的层次化内存池系统。它通过创建层次结构的内存上下文,自动处理内存释放和析构,减少内存泄漏的风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://talloc.samba.org/talloc/doc/html/index.html

阅读FreeRadius源码时,发现内存管理使用的是talloc,而不是malloc。现在来学习一下怎么使用talloc。

What is talloc

Talloc is a hierarchical, reference counted memory pool system with destructors. It is built atop the C standard library and it defines a set of utility functions that altogether simplifies allocation and deallocation of data, especially for complex structures that contain many dynamically allocated elements such as strings and arrays.

Talloc是一个层次化、具备引用计数和析构功能的内存池系统。它在C标准库的基础上定义了一组工具,简化了分配/释放内存的操作(特别是对于像string和数组这样包含许多动态分配成员的复杂数据结构)

The main goals of this library are: removing the needs for creating a cleanup function for every complex structure, providing a logical organization of allocated memory blocks and reducing the likelihood of creating memory leaks in long-running applications. All of this is achieved by allocating memory in a hierarchical structure of talloc contexts such that deallocating one context recursively frees all of its descendants as well.

Talloc的主要目标是:

  • 消除为每个复杂数据结构编写清理函数的麻烦
  • 对分配的内存块进行逻辑组织
  • 降低长时间运行的程序出现内存泄露的可能性

上面的三个目标是通过这样的方法实现的:将分配的内存以层次化的数据结构 talloc context进行管理,需要deallocating时递归的对talloc context进行free即可。

主要特点:

  • 开源
  • 层次化的内存模型
  • Natural projection of data structures into the memory space
  • 简化了对较大数据结构的内存管理
  • 内存被释放之前,自动执行“析构函数”
  • 模拟了一个动态类型系统
  • 实现了一个透明的内存池

1. Talloc context

It is a logical unit which represents a memory space managed by talloc.

talloc context的地位是最重要的,它代表了一块由talloc管理的内存空间。
从程序员的角度来看,talloc context与C标准库内存管理工具返回的指针完全相同。也就是说,由talloc返回的context可以直接作为标准库函数的参数来使用。

char *str1 = strdup("I am NOT a talloc context");
char *str2 = talloc_strdup(NULL, "I AM a talloc context");

printf("%d\n", strcmp(str1, str2) == 0);

free(str1);
talloc_free(str2); /* we can not use free() on str2 */

为什么会如此神奇?原因就是:

This is possible because the context is internally handled as a special fixed-length structure called talloc chunk. Each chunk stores context metadata followed by the memory space requested by the programmer. When a talloc function returns a context (pointer), it will in fact return a pointer to the user space portion of the talloc chunk. If we to manipulate this context using talloc functions, the talloc library transforms the user-space pointer back to the starting address of the chunk. This is also the reason why we were unable to use free(str2) in the previous example - because str2 does not point at the beginning of the allocated block of memory. This is illustrated on the next image:

这里写图片描述

context在内部作为固定长度的结构被处理,称为talloc chunk。每个chunk存储context的metadata(元数据),元数据后面是用户请求的内存空间。当某个talloc 函数返回一个context(指针)时,它将会返回该chunk的用户空间的指针。当使用talloc函数操作这个context时,talloc库会将用户空间的指针转换回chunk的起始地址。这也就是为什么上面的context不能使用free释放的原因,因为str2并没有指向动态内存的起始地址。

如上图所示,整个空间用allocated block表示,它由talloc chunk和requested memory两部分构成,给用户返回的context指向requestd memory的起始地址。talloc chunk中应该存放者这个chunk的metadata(引用计数、context size)

1.1 Context meta data

Every talloc context carries several pieces of internal information along with the allocated memory:

context的metadata有:

  • name 用来报告context的层次结构并模拟一个动态类型系统
  • requested memory 的大小
  • 析构函数,在free之前被调用
  • 引用计数
  • child和parent的context 用来创建内存的层次结构

1.2 Hierarchy of talloc context

每个talloc context都包含parent和child的信息。talloc使用这些信息创建一个层次型结构。说句人话,就是以树形结构管理相关的context,树的根节点称为top level context。

使用树形结构的好处:

  • 当释放一个context时,它的child会被正确的释放。
  • 一个context的parent可以改变,可以将一个子树移动到其他树中。
  • 管理数据结构更加自然。

举个栗子:

struct user {
  uid_t uid;
  char *username;
  size_t num_groups;
  char **groups;
};

适应talloc,上述数据结构会被组织成下面的树状结构:
这里写图片描述

/* create new top level context */
struct user *user = talloc(NULL, struct user);

user->uid = 1000;
user->num_groups = N;

/* make user the parent of following contexts */
user->username = talloc_strdup(user, "Test user");
user->groups = talloc_array(user, char*, user->num_groups);

for (i = 0; i < user->num_groups; i++) {
  /* make user->groups the parent of following context */
  user->groups[i] = talloc_asprintf(user->groups,
                                    "Test group %d", i);
}

这个结构体中有许多动态分配的成分,当需要释放时,只需要这么做:

talloc_free(user);

talloc库会为你释放所有的内存。

画了一个内存的层次结构图,黑色箭头指向parent,蓝色虚线指向child,绿色实线指向数据机构中对应的内存。每个节点表示一个context,每个context由metadata(节点的深蓝色部分)和requested memory(节点的浅蓝色)组成。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值