前言
SLUB 是 Linux 默认的通用内核对象分配器。常见小对象 kmalloc() 分配通常会落到某个 kmem_cache(例如 kmalloc-8 ~ kmalloc-8k,具体范围取决于内核版本、页大小和 KMALLOC_MAX_CACHE_SIZE 等配置),更大的分配可能走页分配或大对象路径。内核子系统通过 kmem_cache_create() 建立的专用缓存(dentry、ext4_inode_cache……)也共享同一套管理框架:每个 cache 由若干 slab(order-N 的伙伴页)组成,每个 slab 切成等大的 object。
本文源码路径和行号以 Linux/Android common kernel 的 SLUB 实现为参考;不同 Android 厂商内核常有 backport 和私有补丁,实际排查时应以目标设备的 kernel tree 为准。
当我们分析是否发生 slab 内存泄漏时,一般流程是这样的:
查看
/proc/meminfo,确认Slab、SReclaimable、SUnreclaim是否异常。查看
/proc/slabinfo,确认是哪一个kmem_cache占用异常。做时间序列采样,区分持续增长、峰值残留和可回收缓存。
打开
slub_debug或使用 trace/ftrace/kmemleak 等工具,抓取分配调用栈定位异常模块和函数。
所以本文着手于/proc/slabinfo进行讲解!

slabinfo的代码实现
/proc/slabinfo:mm/slab_common.c 中注册的 seq_file 接口(SLAB/SLUB 共用框架,get_slabinfo() 由具体分配器实现);

接口注册与 seq_file 骨架
/proc/slabinfo 在 mm/slab_common.c:1193 的 slab_proc_init() 中注册,权限 SLABINFO_RIGHTS——对 SLUB 是 0400(只读、仅 root):
static int __init slab_proc_init(void)
{
proc_create("slabinfo", SLABINFO_RIGHTS, NULL, &slabinfo_proc_ops);
return 0;
}
module_init(slab_proc_init);
输出走标准 seq_file 迭代器(mm/slab_common.c:1172):
static const struct seq_operations slabinfo_op = {
.start = slab_start,
.next = slab_next,
.stop = slab_stop,
.show = slab_show,
};
"迭代单元"就是全局链表 slab_caches 上的每一个 kmem_cache:
void *slab_start(struct seq_file *m, loff_t *pos)
{
mutex_lock(&slab_mutex); // 整个读取期间持有 slab_mutex
return seq_list_start(&slab_caches, *pos); // 定位到第 *pos 个 cache
}
void *slab_next(struct seq_file *m, void *p, loff_t *pos)
{
return seq_list_next(p, &slab_caches, pos);
}
void slab_stop(struct seq_file *m, void *p)
{
mutex_unlock(&slab_mutex);
}
slab_show() 对第一个元素打印表头,然后对每个 cache 调用 cache_show() (mm/slab_common.c:1085):
static void cache_show(struct kmem_cache *s, struct seq_file *m)
{
struct slabinfo sinfo;
memset(&sinfo, 0, sizeof(sinfo));
get_slabinfo(s, &sinfo); // ← 数字从这来
seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
s->name, sinfo.active_objs, sinfo.num_objs, s->size,
sinfo.objects_per_slab, (1 << sinfo.cache_order));
seq_printf(m, " : tunables %4u %4u %4u", ...); // SLUB 下恒为 0
seq_printf(m, " : slabdata %6lu %6lu %6lu", ...);
slabinfo_show_stats(m, s); // SLUB 下是空函数
seq_putc(m, '\n');
}
表头(print_slabinfo_header(),mm/slab_common.c:1048)即我们熟悉的 slabinfo - version: 2.1 两行。
数字从哪来:SLUB 版 get_slabinfo()

get_slabinfo() 声明为分配器各实现一份,SLUB 版本在 mm/slub.c:6309:
void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo)
{
unsigned long nr_slabs = 0;
unsigned long nr_objs = 0;
unsigned long nr_free = 0;
int node;
struct kmem_cache_node *n;
for_each_kmem_cache_node(s, node, n) {
nr_slabs += node_nr_slabs(n); // atomic_long_read(&n->nr_slabs)
nr_objs += node_nr_objs(n); // atomic_long_read(&n->total_objects)
nr_free += count_partial(n, count_free); // 遍历 partial 链表统计空闲 object
}
sinfo->active_objs = nr_objs - nr_free;
sinfo->num_objs = nr_objs;
sinfo->active_slabs = nr_slabs;
sinfo->num_slabs = nr_slabs;
sinfo->objects_per_slab = oo_objects(s->oo); // 每个 slab 切几个 object
sinfo->cache_order = oo_order(s->oo); // 每个 slab 占 2^order 页
}
三个关键语义,直接决定了如何正确读 slabinfo:
total_objects/nr_slabs在 slab 页诞生/销毁时增减 (alloc_slab_page()中atomic_long_inc(&n->nr_slabs); atomic_long_add(objects, &n->total_objects),free_slab()中反向操作)。因此它们包含 per-cpu 活跃 slab(c->page)和 per-cpu partial 链表上的 slab,不只是 node 链表上可见的部分。空闲 object 只遍历各 node 的 partial 链表统计。per-cpu 活跃 slab 的 freelist 不会被扫到——也就是说,per-cpu 缓存里"空闲但尚未归还"的 object 会被计入
active_objs。因此active_objs是 slabinfo 视角下的近似活跃对象数,不等价于精确的 live allocation;CPU 数较多、per-cpu partial 较多或系统压力较大时,这个偏差可能被放大。SLUB 下
active_slabs == num_slabs恒成立(都等于nr_slabs),表头里 "active/total slab" 两列在 SLUB 上没有区分度——这是 SLAB 分配器遗留的 ABI 形状。
tunables <limit> <batchcount> <sharedfactor> 和 slabdata ... <sharedavail> 是 SLAB 分配器的批量分配/共享数组概念,SLUB 没有对应物,slabinfo 里写死为 0。 slabinfo_show_stats() 在 SLUB 里是空函数(mm/slub.c:6331)。 写路径 slabinfo_write() 同样直接返回 -EIO(mm/slub.c:6335)——SLUB 下 /proc/slabinfo 是纯只读文件;只有 SLAB(SLABINFO_RIGHTS=0600)才支持写 tunables。
顺带一提,get_slabinfo() 还被 OOM 路径复用:dump_unreclaimable_slab() (mm/slab_common.c:1114)在 OOM 时遍历 slab_caches,把所有没有 SLAB_RECLAIM_ACCOUNT 标记的 cache 的用量打到内核日志,作为 OOM 报告的一部分。
输出逐列解读
一次真实的 cat /proc/slabinfo :
spring:/ $ cat /proc/slabinfo
slabinfo - version: 2.1
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
zspage 42237 134758 56 73 1 : tunables 0 0 0 : slabdata 1846 1846 0
zs_handle 251097 796672 8 512 1 : tunables 0 0 0 : slabdata 1556 1556 0
dm_verity_fec_buffers 8 8 4048 8 8 : tunables 0 0 0 : slabdata 1 1 0
dm_bufio_buffer 26 26 152 26 1 : tunables 0 0 0 : slabdata 1 1 0
dm_bufio_buffer 26 26 152 26 1 : tunables 0 0 0 : slabdata 1 1 0
dm_bufio_buffer-4 100 100 160 25 1 : tunables 0 0 0 : slabdata 4 4 0
dm_bufio_buffer-4 50 50 160 25 1 : tunables 0 0 0 : slabdata 2 2 0
dm_bufio_buffer-4 75 75 160 25 1 : tunables 0 0 0 : slabdata 3 3 0
dm_bufio_buffer-4 125 125 160 25 1 : tunables 0 0 0 : slabdata 5 5 0
dm_bufio_buffer-4 75 75 160 25 1 : tunables 0 0 0 : slabdata 3 3 0
dm_bufio_buffer-4 50 50 160 25 1 : tunables 0 0 0 : slabdata 2 2 0
dm_bufio_buffer-4 25 25 160 25 1 : tunables 0 0 0 : slabdata 1 1 0
dm_bufio_buffer-4 50 50 160 25 1 : tunables 0 0 0 : slabdata 2 2 0
dm_bufio_buffer-4 50 50 160 25 1 : tunables 0 0 0 : slabdata 2 2 0
dm_bufio_buffer-4 50 50 160 25 1 : tunables 0 0 0 : slabdata 2 2 0
dm_bufio_buffer-4 50 50 160 25 1 : tunables 0 0 0 : slabdata 2 2 0
dm_bufio_buffer-4 25 25 160 25 1 : tunables 0 0 0 : slabdata 1 1 0
//...
fscrypt_info 1922 4890 136 30 1 : tunables 0 0 0 : slabdata 163 163 0
wakeup_irq_node_cache 128 128 32 128 1 : tunables 0 0 0 : slabdata 1 1 0
AF_VSOCK 176 176 1472 22 8 : tunables 0 0 0 : slabdata 8 8 0
bridge_fdb_cache 0 0 128 32 1 : tunables 0 0 0 : slabdata 0 0 0
nf-frags 0 0 200 20 1 : tunables 0 0 0 : slabdata 0 0 0
xfrm6_tunnel_spi 0 0 128 32 1 : tunables 0 0 0 : slabdata 0 0 0
ip6-frags 0 0 200 20 1 : tunables 0 0 0 : slabdata 0 0 0
fib6_nodes 256 256 128 32 1 : tunables 0 0 0 : slabdata 8 8 0
ip6_dst_cache 256 256 256 32 2 : tunables 0 0 0 : slabdata 8 8 0
ip6_mrt_cache 0 0 192 21 1 : tunables 0 0 0 : slabdata 0 0 0
PINGv6 0 0 1344 24 8 : tunables 0 0 0 : slabdata 0 0 0
RAWv6 216 216 1344 24 8 : tunables 0 0 0 : slabdata 9 9 0
UDPLITEv6 0 0 1472 22 8 : tunables 0 0 0 : slabdata 0 0 0
UDPv6 198 198 1472 22 8 : tunables 0 0 0 : slabdata 9 9 0
tw_sock_TCPv6 232 232 280 29 2 : tunables 0 0 0 : slabdata 8 8 0
request_sock_TCPv6 0 0 328 24 2 : tunables 0 0 0 : slabdata 0 0 0
TCPv6 108 108 2560 12 8 : tunables 0 0 0 : slabdata 9 9 0
xt_hashlimit 272 272 120 34 1 : tunables 0 0 0 : slabdata 8 8 0
nf_conncount_rb 0 0 96 42 1 : tunables 0 0 0 : slabdata 0 0 0
nf_conncount_tuple 0 0 72 56 1 : tunables 0 0 0 : slabdata 0 0 0
nf_conntrack_expect 0 0 232 35 2 : tunables 0 0 0 : slabdata 0 0 0
nf_conntrack 600 600 320 25 2 : tunables 0 0 0 : slabdata 24 24 0
fq_flow_cache 0 0 128 32 1 : tunables 0 0 0 : slabdata 0 0 0
ashmem_range_cache 512 512 64 64 1 : tunables 0 0 0 : slabdata 8 8 0
ashmem_area_cache 702 702 312 26 2 : tunables 0 0 0 : slabdata 27 27 0
dm_snap_pending_exception 0 0 128 32 1 : tunables 0 0 0 : slabdata 0 0 0
dm_exception 0 0 32 128 1 : tunables 0 0 0 : slabdata 0 0 0
kcopyd_job 0 0 3384 9 8 : tunables 0 0 0 : slabdata 0 0 0
io 1344 1344 64 64 1 : tunables 0 0 0 : slabdata 21 21 0
dm_uevent 0 0 2888 11 8 : tunables 0 0 0 : slabdata 0 0 0
wg_peer 0 0 1760 18 8 : tunables 0 0 0 : slabdata 0 0 0
allowedips_node 0 0 72 56 1 : tunables 0 0 0 : slabdata 0 0 0
trace_event_file 2024 2024 88 46 1 : tunables 0 0 0 : slabdata 44 44 0
ftrace_event_field 6862 6862 56 73 1 : tunables 0 0 0 : slabdata 94 94 0
pool_workqueue 384 384 256 32 2 : tunables 0 0 0 : slabdata 12 12 0
maple_node 20929 45664 256 32 2 : tunables 0 0 0 : slabdata 1427 1427 0
radix_tree_node 42247 110768 584 28 4 : tunables 0 0 0 : slabdata 3956 3956 0
task_group 64 64 512 32 4 : tunables 0 0 0 : slabdata 2 2 0
mm_struct 544 544 1024 32 8 : tunables 0 0 0 : slabdata 17 17 0
vmap_area 15877 31680 64 64 1 : tunables 0 0 0 : slabdata 495 495 0
kmalloc-rcl-8k 0 0 8192 4 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-4k 0 0 4096 8 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-2k 0 0 2048 16 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-1k 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-512 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-256 0 0 256 32 2 : tunables 0 0 0 : slabdata 0 0 0
kmalloc-rcl-192 1134 1134 192 21 1 : tunables 0 0 0 : slabdata 54 54 0
kmalloc-rcl-128 1376 1568 128 32 1 : tunables 0 0 0 : slabdata 49 49 0
kmalloc-rcl-64 2426 4096 64 64 1 : tunables 0 0 0 : slabdata 64 64 0
kmalloc-8k 1405 1424 8192 4 8 : tunables 0 0 0 : slabdata 356 356 0
kmalloc-4k 4348 4400 4096 8 8 : tunables 0 0 0 : slabdata 550 550 0
kmalloc-2k 3815 4304 2048 16 8 : tunables 0 0 0 : slabdata 269 269 0
kmalloc-1k 9343 9408 1024 32 8 : tunables 0 0 0 : slabdata 294 294 0
kmalloc-512 10527 12928 512 32 4 : tunables 0 0 0 : slabdata 404 404 0
kmalloc-256 5908 6048 256 32 2 : tunables 0 0 0 : slabdata 189 189 0
kmalloc-192 11417 15540 192 21 1 : tunables 0 0 0 : slabdata 740 740 0
kmalloc-128 74961686 74966336 128 32 1 : tunables 0 0 0 : slabdata 2342698 2342698 0
kmalloc-64 263841 277632 64 64 1 : tunables 0 0 0 : slabdata 4338 4338 0
kmem_cache_node 576 576 64 64 1 : tunables 0 0 0 : slabdata 9 9 0
kmem_cache 448 448 256 32 2 : tunables 0 0 0 : slabdata 14 14 0
核心公式:slab 实际吃掉的物理内存 = num_slabs × pagesperslab × PAGE_SIZE。 注意不是 active_objs × objsize——后者只是"装进去多少数据",前者才是"占了多少页"。多数 Android 设备长期使用 4KB 页,但新平台可能使用 16KB 页,因此现场计算时不要把页大小写死。

实例:定位 "slab 内存去哪了"
我们就以上面一个章节展示的 slabinfo 来作为实例场景来分析一下slab内存去哪里了?
其实从 slabinfo 中我们可以非常容易的得到 kmalloc-128 的内存是异常的!
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
kmalloc-128 74961686 74966336 128 32 1 : tunables 0 0 0 : slabdata 2342698 2342698 0
字段逐项解读
name:kmalloc-128。这是内核中最常用的通用内存分配器,专门分配128字节大小的内存块。很多内核驱动、网络数据包结构、临时缓冲都会用到它。active_objs(74,961,686): 当前正在使用中的对象数量。约 7496万 个。num_objs(74,966,336): 内核已经向系统申请并准备好的对象总数(包括空闲的)。约 7496万 个。objsize(128): 每个对象 128 字节。objperslab(32): 每个 slab 页块里包含 32 个这样的对象。pagesperslab(1): 每个 slab 占用 1 个物理页。页大小以目标设备PAGE_SIZE为准,常见是 4KB,也可能是 16KB。tunables(0 0 0): SLAB 分配器遗留调优字段,SLUB 下无实际意义。slabdata:active_slabs(2,342,698): 当前有约 234万个 slab 处于活跃状态。num_slabs(2,342,698): slab 总数为 234万。sharedavail(0): 无共享可用。
计算
自洽校验
74,966,336(num_objs) ÷ 32(objperslab) = 2,342,698(num_slabs) ✓
内存占用庞大:
若目标设备页大小为 4KB:
总内存 = num_slabs (2,342,698) × pagesperslab (1) × 4KB ≈ 9.37 GB。kmalloc-128 这一个缓存就占用了接近 10 GB 的内存!
在用量巨高
active_objs(74,961,686) × objsize(128b) ≈ 8.94 GiB
占用率极高:
active_objs(74,961,686) / num_objs(74,966,336) = 99.99%
空闲slab object : num_objs(74,966,336) - active_objs(74,961,686) = 4650
活跃对象几乎等于总对象数(差额仅 4,650 个)。这意味着 99.99% 的 128字节内存块都被内核占用着,几乎没有空闲缓存可用。
99.99% 满、空闲对象几乎为零——这说明它不像“cache 中大量空闲 object 尚未归还”这一类问题,更像确实有约 7500 万个 128 字节对象仍被内核持有。但单次快照不能直接等同于泄漏,还需要结合时间序列和调用栈确认。
顺带解读布局列:
objperslab=32, pagesperslab=1是calculate_order()(mm/slub.c:3825)的标准输出——它先取min_objects = 4×(fls(nr_cpus)+1), 从满足它的最低 order 起找"页内剩余rem = slab_size % size最小"的布局; 128B 在 order-0 页上4096 % 128 = 0零浪费,直接命中 32 obj/页。 核数很多的大机器上min_objects抬高,同一 cache 可能变成 order-1(64 obj/2 页), 所以 objperslab 与机器 CPU 数相关,不是固定值。

对比另一种形态:active_objs 远小于 num_objs(比如 dentry 用了 12000 个 slab 但 active 只有 3 万/23 万)——说明大量 slab 处于空闲/半空状态,更常见原因是负载波动后 SLUB 还没归还、cache 可回收但尚未触发 shrink、per-cpu/node partial 残留或对象布局导致的内部碎片。是否泄漏要看 active_objs 是否持续增长,而不是只看 active_objs / num_objs 一次快照。
Android 现场排查流程
Android 设备上排查 slab 问题时,不建议只截一份 /proc/slabinfo 就下结论。更稳妥的流程是先确认总量,再找 cache,再看趋势,最后抓调用栈。

1. 先从 meminfo 判断 slab 类型
adb root
adb shell "grep -E 'Slab|SReclaimable|SUnreclaim|KReclaimable' /proc/meminfo"
重点看:
Slab:内核 slab 总量。SReclaimable/KReclaimable:理论上可回收的 slab,例如部分 inode/dentry 类缓存。SUnreclaim:不可回收 slab,更容易直接压缩可用内存空间,也是 Android 低内存问题中更需要优先关注的部分。
如果 Slab 高但主要落在 SReclaimable,排查方向偏向文件系统缓存、dcache/inode shrinker 是否正常、是否存在负载峰值残留。如果 SUnreclaim 持续增长,则更要怀疑驱动、网络、Binder、GPU、SELinux、kmalloc-* 等不可回收对象。
2. 对 slabinfo 按真实占页排序
adb shell "cat /proc/slabinfo" > slabinfo.txt
adb shell "awk 'NR>2 {bytes=\$15*\$6*4096; printf \"%12s %-32s active=%-12s total=%-12s size=%-8s objslab=%-6s pages=%-4s slabs=%-10s\n\", bytes,\$1,\$2,\$3,\$4,\$5,\$6,\$15}' /proc/slabinfo | sort -nr | head -40"
上面的 4096 只适合 4KB page 设备。若目标平台是 16KB page,需要替换为 16384。真正的判断公式始终是:
bytes = num_slabs * pagesperslab * PAGE_SIZE
3. 做时间序列,而不是只看单点
adb shell "while true; do date; grep -E 'kmalloc-128|dentry|inode_cache|vm_area_struct|binder|kgsl|zspage|zs_handle' /proc/slabinfo; sleep 10; done"
判断方式:
num_slabs和active_objs持续单调增长:高度怀疑泄漏或长期持有。active_objs增长后稳定,num_objs高位不降:可能是峰值负载后 cache 未及时回收。active_objs低但num_objs高:优先看可回收性、shrink 行为、per-cpu/node partial 和碎片,而不是直接定性为泄漏。只有
kmalloc-*增长:只能说明对象大小,不能说明归属模块,必须抓分配调用栈。
Android 常见需要额外关注的 cache 或相关方向包括:binder/binder_node、kgsl/adreno、ion/dma-buf、ashmem、zspage/zs_handle、skbuff_*、TCP/UDP、dentry/inode_cache、f2fs/ext4、SELinux 相关 avc_*/lsm_*。
深入定位 —— 从 slabinfo 到"谁在分配"

前面我们通过 slabinfo 确认了 kmalloc-128 异常,但它只能告诉我们"哪里"出了问题,无法回答"谁"在分配。这就好比医生测出你发烧了,但不知道是病毒还是细菌感染。
slabinfo 只能提供聚合统计,不记录调用栈信息:
不知道是哪个内核模块在申请
不知道是哪些函数路径在分配
不知道分配/释放的频率模式
所以,我们需要更强的工具来补齐调用栈信息。常用选择如下:
注意: 这里只简单说明一下,关于这些工具如何参与进slab内存泄漏的分析流程中,会在本博客的其他博文中详细说明
1. slub_debug / sysfs trace
如果内核打开了 CONFIG_SLUB_DEBUG,可以通过 bootargs 或 sysfs 针对目标 cache 打开跟踪。以 kmalloc-128 为例,不同内核暴露能力略有差异,现场先检查:
adb shell "ls -l /sys/kernel/slab/kmalloc-128"
adb shell "cat /sys/kernel/slab/kmalloc-128/trace 2>/dev/null"
如果支持 trace,可打开分配跟踪后复现问题,再读取 alloc_traces / free_traces:
adb shell "echo 1 > /sys/kernel/slab/kmalloc-128/trace"
adb shell "cat /sys/kernel/slab/kmalloc-128/alloc_traces"
adb shell "cat /sys/kernel/slab/kmalloc-128/free_traces"
注意:slub_debug 对性能和内存都有额外开销,线上用户版本通常不可直接开启,建议在 userdebug/eng 或专项复现版本中使用。
2. ftrace/kmem tracepoint
如果设备允许使用 ftrace,可以抓 kmem:kmalloc、kmem:kfree、kmem:kmem_cache_alloc、kmem:kmem_cache_free 等事件,结合调用栈过滤目标大小或目标 cache:
adb shell "echo 0 > /sys/kernel/tracing/tracing_on"
adb shell "echo 1 > /sys/kernel/tracing/events/kmem/kmalloc/enable"
adb shell "echo 1 > /sys/kernel/tracing/options/stacktrace"
adb shell "echo > /sys/kernel/tracing/trace"
adb shell "echo 1 > /sys/kernel/tracing/tracing_on"
# 复现问题
adb shell "echo 0 > /sys/kernel/tracing/tracing_on"
adb shell "cat /sys/kernel/tracing/trace" > kmem_trace.txt
这条路径适合短时间复现。长时间开启会产生大量日志和明显开销。部分 Android 内核仍使用 /sys/kernel/debug/tracing 路径,若 /sys/kernel/tracing 不存在,需要切换到对应 debugfs 路径并确认 debugfs 已挂载。
3. kmemleak / KASAN / vendor debug
如果问题是“分配后永不释放”,CONFIG_DEBUG_KMEMLEAK 可以直接扫描疑似泄漏对象;如果怀疑越界、use-after-free,优先使用 KASAN/KFENCE。Android 厂商内核还可能有私有 debugfs 节点或内存统计,例如 GPU、IPA、camera、display、dma-buf/bufinfo 等,应结合异常 cache 名称反查对应子系统。
/proc/slabinfo 的角色是定位“哪个 cache 异常”,不是直接回答“谁泄漏”。真正闭环至少需要:异常 cache + 时间趋势 + 调用栈 + 复现动作 + 代码释放路径审计。
总结
本文主要就是介绍 /proc/slabinfo 节点的详细介绍,并以一个 kmalloc-128 slab内存泄漏的案例作为案例来确定分析slab内存泄漏的方法!同时我们也简明的说明了一些常见的slab内存泄漏的分析方法。

但是需要注意的是:
不能等问题爆发才去排查。建议建立 slab 内存的常态化监控: