当前位置: 首页 > 面试题库 >

是否有办法仅查看生成的核心文件来定位进程的哪一部分使用了大部分内存?

慕容明煦
2023-03-14
问题内容

我有一个进程(每次由看门狗启动,由于某种原因它都停止了),通常使用大约200MB内存。一旦我看到它耗尽了内存-
内存使用量约为1.5-2GB,这肯定意味着某个地方出现了“内存泄漏”(引号中的“内存泄漏”,因为这不是真正的内存泄漏-就像分配的内存一样,从未释放过
,无法访问 -请注意, 仅使用了智能指针 。因此,我想到了一个巨大的容器(我没有找到)或类似的东西)

后来,由于高内存使用率并生成了一个核心转储-
大约2GB,该过程崩溃了。但是问题是,我无法重现该问题,因此valgrind在这里无济于事(我想)。这种情况很少发生,我无法“抓住”。

因此,我的问题是-有没有办法使用exe和核心文件来定位过程的哪一部分使用了大部分内存?

我用来查看了核心文件gdb,没有什么异常。但是核心很重要,因此必须有一些东西。有没有一种聪明的方法来了解发生了什么,或者只是猜测可能会有所帮助(但是对于这么大的exe
..,有12个线程,大约50-100个(可能更多)类,等等,等等)

这是一个C++在RHEL5U3上运行的html" target="_blank">应用程序。


问题答案:

以十六进制格式(作为字节/字/ dwords /
qwords)打开此核心转储。从文件的中间开始,尝试注意任何重复的模式。如果找到任何内容,请尝试确定起始地址和某些可能的数据结构的长度。使用此结构的长度和内容,尝试猜测可能是什么。使用该地址,尝试找到一些指向此结构的指针。重复直到您进入堆栈或某个全局变量。如果使用堆栈变量,您将很容易知道此链从哪个函数开始。对于全局变量,至少要知道其类型。

如果您在核心转储中找不到任何模式,则泄漏结构的可能性很大。只需将文件中看到的内容与程序中所有大型结构的可能内容进行比较即可。

更新资料

如果您的coredump具有有效的调用栈,则可以从检查其功能开始。搜索任何异常的东西。检查调用堆栈顶部附近的内存分配是否请求过多。检查调用堆栈函数中是否存在无限循环。

词语“ 仅使用智能指针
”使我感到恐惧。如果这些智能指针的重要部分是共享指针(shared_ptr,intrusive_ptr等),则与其搜索大型容器,不如搜索共享指针周期。

更新2

尝试确定堆在corefile中结束的位置(brk值)。在gdb下运行coredumped进程并使用pmap命令(从其他终端)。gdb也应该知道这个值,但是我不知道该怎么问…如果大多数进程的内存都在上方brk,则可以通过较大的内存分配(很可能是std
:: vector)来限制搜索。

为了增加在现有核心转储的堆区域中发现泄漏的机会,可以使用一些编码(我自己并没有这样做,只是一个理论):

  • 读取coredump文件,将每个值解释为一个指针(忽略代码段,未对齐的值以及指向非堆区域的指针)。对列表进行排序,计算相邻元素的差异。
  • 此时,整个内存将拆分为许多可能的结构。计算结构大小的直方图,删除任何无关紧要的值。
  • 计算这些指针所属的指针和结构的地址差。对于每种结构大小,计算指针位移的直方图,然后再次删除所有无关紧要的值。
  • 现在,您有足够的信息来猜测结构类型或构造结构的有向图。查找该图的源节点和周期。您甚至可以像在“列出“冷”存储区”中一样可视化该图。

Coredump文件为elf格式。从其标头仅需要数据段的开始和大小。为了简化过程,只需将其读取为线性文件,忽略结构即可。



 类似资料:
  • 我有两个分支(和master)。分支2基于分支1基于master。我已经提交了分支1进行审查,它有一些更改,我将其中一些更改重新基于历史并将结果合并到master中。 现在我需要将Branch 2放在master之上,为审查/合并做准备。 问题是分支2仍然包含分支1的原始提交,这些提交已经不存在了,所以git会感到困惑。我尝试rebase -i删除分支1的原始提交,但是分支2的提交并不基于分支1之

  • 问题内容: 我们有一台服务器(用C和C ++编写),当前可以捕获SEGV并将一些内部信息转储到文件中。我想生成一个核心文件,并在捕获SEGV时将其写入磁盘,因此我们的支持代表和客户不必大惊小怪的ulimit,然后等待崩溃再次发生才能获得核心文件。过去我们使用过abort函数,但是它受ulimit规则的约束,无济于事。 我们有一些旧的代码可以读取/ proc / pid / map并手动生成一个核心

  • 从引导加载程序内核 如果看过我在这之前的文章,你就会知道我已经开始涉足底层的代码编写。我写了一些关于 Linux x86_64 汇编的文章。同时,我开始深入研究 Linux 源代码。底层是如何工作的,程序是如何在电脑上运行的,它们是如何在内存中定位的,内核是如何管理进程和内存,网络堆栈是如何在底层工作的等等,这些我都非常感兴趣。因此,我决定去写另外的一系列文章关于 x86_64 框架的 Linux

  • 这个开发手册的第一部分描述了Spring Framework所有使用到的技术领域。 首先是Spring Framework中的控制翻转(IoC)容器。在完整的阐述了Spring Framework的IoC容器后紧跟的是对Spring的面向方面编程(AOP)技术的全面说明。 Spring Framework拥有自己的AOP框架,这个框架在概念上是十分容易理解的,而且它成功地实现了在Java企业级开发

  • 简介 内存管理是操作系统内核中最复杂的部分之一(我认为没有之一)。在讲解内核进入点之前的准备工作时,我们在调用 start_kernel 函数前停止了讲解。start_kernel 函数在内核启动第一个 init 进程前初始化了所有的内核特性(包括那些依赖于架构的特性)。你也许还记得在引导时建立了初期页表、识别页表和固定映射页表,但是复杂的内存管理部分还没有开始工作。当 start_kernel

  • 由邮递员生成以下代码: 此请求在服务器上生成一个大小为0 Kb的文件。而且我无法放文件。所以,我必须放一个这样的文件: 但我有一个超时选项。 如何使用这种Rest API放置文件?