malloc_trim() 可以从堆中间释放内存吗?

2023-11-30

我对 glibc 中实现的 malloc_trim 的行为感到困惑。

man malloc_trim
[...]
malloc_trim - release free memory from the top of the heap
[...]
This function cannot release free memory located at places other than the top of the heap.

当我现在查找来源时malloc_trim()(在 malloc/malloc.c 中)我看到它调用mtrim()这是利用madvise(x, MADV_DONTNEED)将内存释放回操作系统。

所以我想知道手册页是否错误,或者我是否误解了 malloc/malloc.c 中的源代码。

Can malloc_trim()从堆中间释放内存?


有两种用法madvise with MADV_DONTNEED现在在 glibc 中:

 H A D  arena.c 643 __madvise ((char *) h + new_size, diff, MADV_DONTNEED);
 H A D  malloc.c    4535 __madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);

https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc由 Ulrich Drepper 于 2007 年 12 月 16 日提交(glibc 2.9 及更高版本的一部分):

  • malloc/malloc.c (public_mTRIm):迭代所有 arenas 并调用

mTRIm 适合所有人。 (mTRIm):另外迭代所有空闲块并使用 madvise 为所有包含至少一个的块释放内存 内存页。

mTRIm (now mtrim) 实施已更改。块中未使用的部分、按页面大小对齐且大小大于页面的部分可以标记为MADV_DONTNEED:

           /* See whether the chunk contains at least one unused page.  */
           char *paligned_mem = (char *) (((uintptr_t) p
                                           + sizeof (struct malloc_chunk)
                                           + psm1) & ~psm1);

           assert ((char *) chunk2mem (p) + 4 * SIZE_SZ <= paligned_mem);
           assert ((char *) p + size > paligned_mem);

           /* This is the size we could potentially free.  */
           size -= paligned_mem - (char *) p;

           if (size > psm1)
               madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);

的手册页malloc_trim有没有:https://github.com/mkerrisk/man-pages/blob/master/man3/malloc_trim.3这是 kerrisk 在 2012 年做出的承诺:https://github.com/mkerrisk/man-pages/commit/a15b0e60b297e29c825b7417582a33e6ca26bf65

如我所能grep glibc 的 git,glibc 中没有手册页,并且没有提交 malloc_trim 联机帮助页来记录此补丁。 glibc malloc 最好也是唯一的文档是它的源代码:https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c

Additional functions:
 malloc_trim(size_t pad);
 609 /*
 610   malloc_trim(size_t pad);
 611 
 612   If possible, gives memory back to the system (via negative
 613   arguments to sbrk) if there is unused memory at the `high' end of
 614   the malloc pool. You can call this after freeing large blocks of
 615   memory to potentially reduce the system-level memory requirements
 616   of a program. However, it cannot guarantee to reduce memory. Under
 617   some allocation patterns, some large free blocks of memory will be
 618   locked between two used chunks, so they cannot be given back to
 619   the system.
 620 
 621   The `pad' argument to malloc_trim represents the amount of free
 622   trailing space to leave untrimmed. If this argument is zero,
 623   only the minimum amount of memory to maintain internal data
 624   structures will be left (one page or less). Non-zero arguments
 625   can be supplied to maintain enough trailing space to service
 626   future expected allocations without having to re-obtain memory
 627   from the system.
 628 
 629   Malloc_trim returns 1 if it actually released any memory, else 0.
 630   On systems that do not support "negative sbrks", it will always
 631   return 0.
 632 */
 633 int      __malloc_trim(size_t);
 634 

从块的中间释放没有记录为 malloc/malloc.c 中的文本(并且malloc_trimCommend 中的描述在 2007 年没有更新)并且没有记录在手册页项目中。 2012 年的手册页可能是该函数的第一个手册页,不是由 glibc 的作者编写的。 glibc 的信息页面仅提到 128 KB 的 M_TRIM_THRESHOLD:https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html#Malloc-Tunable-Parameters并且不列出 malloc_trim 函数https://www.gnu.org/software/libc/manual/html_node/Summary-of-Malloc.html#Summary-of-Malloc(它也不记录 memusage/memusagestat/libmemusage.so)。

您可以再次询问 Drepper 和其他 glibc 开发人员,就像您在https://sourceware.org/ml/libc-help/2015-02/msg00022.html“malloc_trim() 行为”,但他们仍然没有回复。 (只有其他用户的错误答案,例如https://sourceware.org/ml/libc-help/2015-05/msg00007.html https://sourceware.org/ml/libc-help/2015-05/msg00008.html)

或者您可以测试malloc_trim用这个简单的 C 程序(test_malloc_trim.c) and strace/ltrace:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>

int main()
{
    int *m1,*m2,*m3,*m4;
    printf("%s\n","Test started");
    m1=(int*)malloc(20000);
    m2=(int*)malloc(40000);
    m3=(int*)malloc(80000);
    m4=(int*)malloc(10000);
    printf("1:%p 2:%p 3:%p 4:%p\n", m1, m2, m3, m4);
    free(m2);
    malloc_trim(0); // 20000, 2000000
    sleep(1);
    free(m1);
    free(m3);
    free(m4);
    // malloc_stats(); malloc_info(0, stdout);
    return 0;
}

gcc test_malloc_trim.c -o test_malloc_trim, strace ./test_malloc_trim

write(1, "Test started\n", 13Test started
)          = 13
brk(0)                                  = 0xcca000
brk(0xcef000)                           = 0xcef000
write(1, "1:0xcca010 2:0xccee40 3:0xcd8a90"..., 441:0xcca010 2:0xccee40 3:0xcd8a90 4:0xcec320
) = 44
madvise(0xccf000, 36864, MADV_DONTNEED) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0x7ffffafbfff0)       = 0
brk(0xceb000)                           = 0xceb000

所以,有madvise with MADV_DONTNEED之后的 9 页malloc_trim(0)当堆中间有 40008 字节的空洞时调用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

malloc_trim() 可以从堆中间释放内存吗? 的相关文章

  • 在 4.x 内核上的 64 位内存中查找系统调用表

    我正在尝试编写一个简单的内核模块来查找 Linux 中的 sys call table 但遇到了一些麻烦 我在这里找到了 32 位 Linux 的基本指南 https memset wordpress com 2011 03 18 sysc
  • bash.sh 运行 cron 的权限被拒绝

    如何在这里使用 bash 脚本运行 cron 我做了如下操作 这里有错误 我想知道如何在 ubuntu 中做到这一点 我现在对它感到震惊 bash sh 文件 bin bash cd var www Controller usr bin p
  • 在 shell 脚本中将脚本目录更改为用户的 homedir

    在我的 bash 脚本中 我需要将当前目录更改为用户的主目录 如果我想更改为用户的foo主目录 从命令行我可以执行以下操作 cd foo 效果很好 但是当我从script它告诉我 bar sh line 4 cd foo No such f
  • Python 线程与 Linux 中的多处理

    基于此question https stackoverflow com questions 807506 threads vs processes in linux我假设创建新流程应该几乎和创造新线程在Linux中 然而 很少的测试显示出截
  • mod_perl 无法看到 /tmp 中的文件

    我有一些 mod perl 代码试图访问 tmp 下的文件 但它抛出 没有这样的文件或目录 错误 我在代码中添加了一个 ls al tmp 来查看 Perl 在目录中看到的内容 它只给了我 和 drwxrwxrwt 2 root root
  • 终止 ssh 会话会终止正在运行的进程

    我正在使用 ssh 连接到我的 ubuntu 服务器 我使用命令启动编码程序 然而 似乎当我的 ssh 会话关闭时 因为我在进入睡眠状态的笔记本电脑上启动它 有没有办法避免这种情况 当然 阻止我的笔记本电脑休眠并不是永久的解决方案 运行你的
  • 编译器特定的内存初始化

    有没有办法保证整个程序中某些对象的静态对象初始化顺序 我有内存分配器 我希望将其作为程序中的第一件事进行分配 因为它们将在整个程序的其他地方使用 并且我想使用这些分配器来分配所有后续内存 我知道这可能是特定于编译器的 因为我不相信 C 标准
  • 查找当前打开的文件句柄数(不是 lsof )

    在 NIX系统上 有没有办法找出当前正在运行的进程中有多少个打开的文件句柄 我正在从正在运行的进程中寻找在 C 中使用的 API 或公式 在某些系统上 见下文 您可以在 proc pid fd 中对它们进行计数 如果不属于其中之一 请参阅下
  • 使用 cudamalloc()。为什么是双指针?

    我目前正在浏览有关的教程示例http code google com p stanford cs193g sp2010 http code google com p stanford cs193g sp2010 学习CUDA 演示的代码 g
  • Bash 脚本错误 [重复]

    这个问题在这里已经有答案了 我想知道下面的脚本有什么错误 我收到错误为 command not foundh line 1 command not foundh line 2 其连续的 我试过添加 但现在工作请告诉我该怎么做 bin bas
  • “以下软件包将被更高优先级的频道取代”是什么意思?

    我正在尝试将 fuzzywuzzy 安装到 64 位 Linux 中的 Anaconda 发行版上 当我这样做时 它试图改变我的conda and conda env to conda forge渠道 如下 我通过以下方式在 anacond
  • 对符号“pthread_key_delete@@GLIBC_2.2.5”的未定义引用

    我正在尝试在 Ubuntu 中创建一个文件 当我创建时 我不断收到此错误 usr bin ld gtest 1 7 0 libgtest a gtest all cc o undefined reference to symbol pthr
  • 使用inotify监控文件

    我正在使用 inotify 来监视本地文件 例如使用 root temp inotify add watch fd root temp mask 删除该文件后 程序将被阻止read fd buf bufSize 功能 即使我创建一个新的 r
  • tcmalloc/jemalloc 和内存池之间有什么区别(以及选择的理由)?

    tcmalloc jemalloc是改进的内存分配器 还引入了内存池以更好地分配内存 那么它们之间有什么区别以及在我的应用中如何选择它们呢 这取决于您的程序的要求 如果您的程序有更多的动态内存分配 那么您 需要从可用的分配器中选择一个内存分
  • 在 Bash 中使用“$RANDOM”生成随机字符串

    我正在尝试使用 Bash 变量 RANDOM创建一个由包含整数和字母数字的变量中的 8 个字符组成的随机字符串 例如 var abcd1234ABCD 我怎样才能做到这一点 使用参数扩展 chars 是可能的字符数 是模运算符 chars
  • Realloc 和 sscanf 到一个函数中

    我有一个文件 里面有num行 每一行包含一个数字 我想将每个数字保存到一个向量中 vet 为什么这段代码不起作用 Segmentation fault core dumped 我认为错误是sscanf in save numbers功能 但
  • 如何在Linux中获取带有图标的活动应用程序

    我想找到一种方法获取活动应用程序的列表及其名称和图标 实际上 我正在使用此命令来获取所有活动进程 wmctrl lp 示例输出 0x03800002 0 3293 user notebook XdndCollectionWindowImp
  • /proc/kmsg 和 dmsg 有什么区别?

    我们通常这样做cat proc kmsg or dmesg从用户空间查看内核日志 我明白了dmesg是一个循环缓冲区 它从kmsg 但是kmsg也不是循环缓冲区 它们之间有什么区别和联系呢 宽松地说 dmesg 是一个转储 proc kms
  • WPF 每次打开和关闭窗口时都会增加内存

    我已经做了非常简单的测试 只是为了了解 wpf 如何与内存一起工作 我用一个窗口创建一个项目 其中有一个Button 第二个窗口完全是空的 当我按下Button单击打开第二个窗口 窗口 1 后面的代码
  • 在linux中将包含word的行从一个文件复制到另一个文件

    我想复制包含某些单词的行file1 to file2 Suppose file1 ram 100 ct 50 gopal 200 bc 40 ravi 50 ct 40 krishna 200 ct 100 file2应该只有包含 ct 的

随机推荐

  • Linq to Entities - SQL“IN”子句

    在 T SQL 中 您可以有如下查询 SELECT FROM Users WHERE User Rights IN Admin User Limited 您将如何在 LINQ to Entities 查询中复制它 有可能吗 你需要彻底改变你
  • 如何生成某个公历年到回历的日期

    我想自动适应或生成一年中的日子 从公历到回历 我的意思是您想选择或写入年份作为示例 选择2015年 获取公历 2015 年的所有日期 然后将其转换为回历并显示回历列表 所以你想返回 2 个列表 list1 公历天列表 vs 另一个列表2 h
  • 添加 QLPreviewController 作为子视图不会加载 PDF

    我正在尝试添加 QLPreviewController 的视图作为子视图 不 我不能使用导航控制器或模式 它仅显示 QLPreviewController 的结构背景 我创建一个并将其添加为子视图 QLPreviewController p
  • 如何设置自定义控件的描述以显示在工具箱中?

    我想在设计时添加一个文本 告诉设计者我的控件是什么到我的自定义控件中 就像这里的 VS 默认控件一样 我努力了 summary但这对我不起作用 如何做呢 你可以用以下方式装饰你的班级Description属性 然后 当您使用以下命令将控件添
  • 如何根据自动缩小的标签为多个标签设置相同的字体比例?

    我有 4 个标签视图 其中一个应该显示较大的数值并设置为自动收缩 我的要求是在自动调整该标签以适合其内容后 将该标签设置为与其他标签相同的字体缩放或大小 以便文本内容在整个过程中看起来统一 设置最小比例因子对其他标签没有帮助 因为它们的内容
  • 为 SBT 依赖项设置 javac 选项

    我在编译通过 GIT 加载的 Java 依赖项时遇到问题 object ApplicationBuild extends Build lazy val project Project root file dependsOn RootProj
  • 使用 ADODB 连接打开存储在 SharePoint 上作为数据源的 Excel 文件

    我正在尝试使用以下 VBA 代码片段打开 Excel 文件作为数据源 Dim cn As ADODB Connection Set cn New ADODB Connection With cn Provider Microsoft ACE
  • 是否可以通过积分加速度计数据随时间的变化来计算速度?

    我想知道是否可以使用 线性 加速度计和指南针来计算速度而不使用位置服务 我想通过计算北 西 上轴的加速度分量并随着时间的推移对它们进行积分来做到这一点 那行得通吗 一般来说 Android 设备上的加速度计噪音太大 无法整合信号并获取速度
  • 如何使用 OpenGL 保存 OpenGL 绘图?

    我用 OpenGL 命令绘制屏幕 我必须将此屏幕保存为 bmp 或 png 格式 但我做不到 我正在使用 glReadpixels 但我无法继续 如何使用 OpenGL 在 C 中保存此绘图 它来了 你必须包含 WinGDI h 我认为 G
  • 使用 JavaScript 按类替换内容

    如何使用 Javascript 按类选择元素来修改内容 实际上我尝试使用这个 document getElementsByClassName myClass innerHTML new content 但什么也没做 如果我通过 ID 选择元
  • 将 DataGrid 列宽度绑定到另一个 DataGrid 的两列

    问题 我该如何绑定StatName Width to Samp1 ActualWidth Samp2 ActualWidth 子问题 为什么是我的WidthConverter函数从未执行 断点从未命中 什么是正确的
  • 为什么线程优先级没有作用?

    namespace HelloWorld class Program static void Main string args Thread t new Thread gt WriteY 11 t Start t IsBackground
  • 将 scipy.quad 与 iε 技巧一起使用:结果不佳

    为了规避柯西原理值 我尝试将使用小位移 i 的积分积分到复平面中以避开极点 然而 从下图可以看出 结果很糟糕 此结果的代码如下所示 您有如何改进此方法的想法吗 为什么它不起作用 我已经尝试更改 或积分中的极限 编辑 我将方法 cauchy
  • JavaScript中将非纯函数变成纯函数的策略是什么

    我开始学习 JavaScript 函数式编程 这可能是一个愚蠢的问题 但我正在尝试解决以函数方式编写的非纯函数 我的问题是应该使用什么策略来在函数式编程范例中实现这一点 const crypto require crypto const e
  • 如何在调用方法之前使方法被被动调用

    就像这样 一个类有一个名为 sayHello 的方法 当类的实例调用 sayHello 时 在调用 sayHello 之前会自动调用另一个类中的方法 示例代码可以是这样的 public class Robot public static v
  • 在折线图上显示图像而不是圆圈

    我创建了一个LineChart使用 MPAndroidChart 库 一切都很好 现在我想做的是显示一个可绘制的 图像 而不是图表上每个条目的默认圆圈 我已经尝试了 API 中的很多选项 但没有成功 谁能告诉我我该怎么做 最后 在尝试了很多
  • 根据另一个向量中的值填充一个向量中的值

    我有两个具有两个不同维度的数据框 1 head x Year GDP deflator 1 1825 NA 2 1826 NA 3 1827 NA 4 1828 NA 5 1829 NA 6 1829 NA 7 1830 NA 8 1830
  • R通过匹配字符串计算频率

    请问有人可以帮我解答这个问题吗 多谢 我有一些这样的数据 A B fruit red apple fruit green apple fruit yellow apple fruit kiwi fruit golden kiwi juice
  • 在 WCF 服务中将 DTO <==> 实体转换器放置在哪里?

    我有以下设计 我的设计 我的设计 http s15 postimg org 3zha8rzqh Design Idea png 我的课程中将有一个名为 ProductDTO 的课程服务层 左侧服务 当调用 更新产品 ProductDTO 操
  • malloc_trim() 可以从堆中间释放内存吗?

    我对 glibc 中实现的 malloc trim 的行为感到困惑 man malloc trim malloc trim release free memory from the top of the heap This function