释放从核心中排除的内存后核心转储大小增加

Posted

技术标签:

【中文标题】释放从核心中排除的内存后核心转储大小增加【英文标题】:Core dump size is increased after freeing memory that was excluded from the core 【发布时间】:2020-11-15 16:56:39 【问题描述】:

我使用 jemalloc 3.6.0-11。 我调用 posix_memalign 来分配一个非常大的块。分配后,我调用madvise(ptr, size, MADV_DONTDUMP); 将这个分配从核心转储中排除。

在释放此内存之前,我调用madvise(ptr, size, MADV_DODUMP);,因为我希望如果这些页面将在未来分配中分配,它们将不会保持标记为 DONTDUMP。

问题是在大多数情况下,我刚刚释放的内存并没有返回给OS(即进程的虚拟内存中仍然包含分配;在/proc//status中分配大小仍然是 VmSize 的一部分);事实证明,核心转储是基于进程的虚拟内存的;所以释放内存后,释放的页面将包含在核心转储中。

有人知道如何解决这个问题吗?

提前致谢!

【问题讨论】:

我不确定madvise 是否真的与此有关。听起来这只是free()d但未返回给操作系统的内存(例如munmap())将继续包含在核心转储中,就像操作系统分配给进程的所有其他内存一样.毕竟,内核无法知道您当前是否正在使用该内存。 我认为您的选择是 (1) 忽略它,(2) 修改或包装 malloc/free 在之后/之前执行 DODUMP/DONTDUMP,(3) 以某种方式安排 malloc 返回您的块当你free()它时到操作系统,(4)绕过malloc,用mmap分配你的块,然后在你完成后自己分配munmap 内存实际分配在哪里?如果它在堆上并且不是使用单独的mmap() 调用创建的,那么调用madvise(ptr, size, MADV_DONTDUMP) 如果不忽略调用则不是一个好主意,因为它可能会导致堆中的其他内存,你可能会很好 需要您的核心转储分析不会被转储,并且您的调用很可能会被忽略,因为它用于堆内存。您是在检查 madvise() 调用的返回值,还是只是假设它们成功了? 【参考方案1】:

你的内存页面对齐了吗?如果不是 the Linux madvise() man page,madvise() 将失败:

   EINVAL `addr` is not page-aligned or `length` is negative.

【讨论】:

【参考方案2】:

我认为到目前为止,解决您的问题的最简单方法是绕过malloc 并直接使用mmap 分配您的大块,完成后使用munmap。这有几个好处:

您知道您可以独占使用相关页面,而不必担心它们会与堆上的其他内容重叠(取决于您请求的对齐方式和大小),也不用担心malloc 的元数据可能在哪里。特别是,您可以随意madvise 他们,而不会影响其他任何事情。

对于一个非常大的块,如果您可以在完成后立即将其返回到操作系统,这对系统的其余部分来说是有礼貌的,而您的 malloc 可能(就像它似乎正在做的那样)坐着用于以后的分配,也许你永远不会这样做。

munmap这个块肯定会确保它不会被转储。

实际上不应该有任何性能问题,因为对于一个非常大的块,posix_memalign 几乎肯定必须从操作系统获取内存,所以无论如何都会有一个系统调用,听起来像你不会非常频繁地分配和释放它。

【讨论】:

听起来很有趣,我会试试的。谢谢!

以上是关于释放从核心中排除的内存后核心转储大小增加的主要内容,如果未能解决你的问题,请参考以下文章

从 Java 堆转储中获取已使用和释放的内存

内存增加每次核心数据迭代

在 C 中使用 free() 时出现无效(中止)核心转储错误

Core Data 不会从内存中释放 UIImage 数据 (ImageIO_PNG_Data)

为啥释放内存后使用的内存量增加了?

在Linux机器上运行C代码时出现分段错误(核心转储)[关闭]