【问题标题】:In what circumstances can malloc_trim(0) cause a crash?在什么情况下 malloc_trim(0) 会导致崩溃?
【发布时间】:2023-02-23 03:54:06
【问题描述】:
我有一段代码,我正在使用 malloc_trim(0) 将任何未使用的内存释放回系统。
但是我断断续续地看到它会导致崩溃。回溯如下:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 mtrim (pad=0, av=0xffff8eebf9f8 <main_arena>) at malloc.c:4771
4771 INTERNAL_SIZE_T size = chunksize (p);
#0 mtrim (pad=0, av=0xffff8eebf9f8 <main_arena>) at malloc.c:4771
#1 __malloc_trim (s=s@entry=0) at malloc.c:4822
我想知道这次崩溃的原因以及如何避免它。
我检查了 malloc_trim() 的手册页,它看起来不会导致崩溃。
【问题讨论】:
标签:
c
memory-management
malloc
free
brk
【解决方案1】:
这是malloc_trim()的手册页:
MALLOC_TRIM(3) Linux 程序员手册 MALLOC_TRIM(3)
姓名
malloc_trim - 从堆顶释放空闲内存
概要
#include <malloc.h>
int malloc_trim(size_t pad);
描述
malloc_trim() 函数尝试释放堆顶部的空闲内存(通过使用合适的参数调用 sbrk(2))。
pad 参数指定在堆顶部保留未修剪的可用空间量。如果此参数为0,则堆顶部仅保留最小内存量(即一页或更少)。非零参数可用于在堆顶部保留一些尾随空间,以便将来进行分配而不必使用 sbrk(2) 扩展堆。
返回值
malloc_trim()函数返回1如果内存实际上被释放回系统,或者0如果不可能释放任何内存。
错误
没有定义错误。
符合
这个函数是一个 GNU 扩展。
笔记
该函数在某些情况下由free(3)自动调用;请参阅mallopt(3)中M_TOP_PAD和M_TRIM_THRESHOLD的讨论。
此函数无法释放位于堆顶部以外的其他位置的空闲内存。
此函数仅释放主区域中的内存。
0 是这个 GNU 扩展函数的完美论据。报告的错误似乎表明堆已损坏,这可能是由您的程序在调用 malloc_trim() 之前引起的。这些错误可能是:
- 修改已分配块末尾或开头之前的字节
- 块被释放后的修改
- 同一块的多个释放
您应该使用 valgrind 等内存工具进行调查,以确定这些问题。
另请注意,malloc_trim() 不可移植,并且在实践中兴趣有限,因为它仅修剪由 sbrk() 分配的遗留堆。现代分配器使用 mmap 来分配不同的区域,并且应该自动处理将未使用的页面释放回操作系统。