C++ 中的运行时内存分析
Posted
技术标签:
【中文标题】C++ 中的运行时内存分析【英文标题】:Runtime memory profiling in C++ 【发布时间】:2011-10-19 04:14:49 【问题描述】:我知道已经有一些使用 massif 和其他工具进行内存分析的线程,但我想知道在生产环境中是否有任何工具或常用技术用于运行时内存分析。
可以想象这样一种实现,其中每个类都提供一个 memSize() 函数,并且通过对所有成员调用 memSize() 并添加自己的大小(或大小估计)来扩展容器以执行相同的操作。然后,您可以随时查询应用程序并查看您的哪些主要数据结构正在使用您的大部分内存,以及这些数据如何随时间变化。
不幸的是,上述策略可能很棘手——您必须处理诸如锁定、内存对齐等问题,有时您不知道第三方数据结构有多大,您必须猜测。总的来说,将它添加到所有类中似乎还需要做很多工作......
那么来看看实际的问题 - 在生产过程中监控内存使用情况和运行时内存增长原因的好方法是什么?
【问题讨论】:
【参考方案1】:如果你愿意:
实现自己的内存管理;或 围绕您正在使用的内存分配/释放函数创建包装器然后您可以跟踪分配的内容、大小和所有者。在我们的嵌入式设备中,我们扩展了内存管理器来记录每个分配的内存块的附加信息。在我们的例子中,我们会跟踪以下内容:
时间戳 线程 ID 块大小 分配时的堆栈跟踪我们有一种机制,我们可以通过该机制要求系统遍历块列表(链表)并将上述每个块的信息转储到 .csv 文件中。这可以在系统内存不足或检测到内存损坏时自动触发,也可以随时手动触发。生成 .csv 文件后,我们有一个 Perl 脚本,它可以消化它并根据原始线程、堆栈跟踪等对请求进行分组。这非常方便,例如,它允许我们查看有多少内存和多少分配来自代码中的给定位置。
我们发现在发现泄漏方面非常有用的一种技术是在某个进程运行时在不同时间生成两个或多个 .csv 报告。通过比较消化的内存日志,我们可以轻松发现内存泄漏。
我们发现添加此信息的开销在于噪音,因此我们在生产系统中启用了此功能,以便当设备在现场发生故障时,我们可以收集 .csv 文件并执行事后分析分析。
【讨论】:
这似乎有很多额外的信息(尤其是堆栈跟踪),打开它对性能有什么影响? 这基本上是地块类型方法的运行时版本,对吧?它的问题是 - 假设你知道你有 100M 字符串并且这是你的大部分内存使用 - 这真的对你有帮助吗?假设你有大量包含字符串的类和集合——你怎么知道是哪一个导致了高使用率……这就是为什么我想更多地考虑遍历显式结构类型的方法 @Matthieu:在我们的嵌入式系统中获取堆栈跟踪并不昂贵。我们没有得到符号,只有帧的地址,为了使其成为固定成本,我们只提取前 6 帧左右。然后作为后期处理,我们使用符号映射将地址转换为符号。 @user779:如果您按堆栈跟踪对分配进行分组,然后在不同时间点对内存块列表进行采样,您可以进行比较并查看代码中哪些位置累积更多分配。以上是关于C++ 中的运行时内存分析的主要内容,如果未能解决你的问题,请参考以下文章
C++异常分析排查软件启动时访问了0xcdcdcdcd内存地址导致内存访问违例的崩溃
Android 逆向修改运行中的 Android 进程的内存数据 ( 使用 IDA 分析要修改的内存特征 | 根据内存特征搜索修改点 | 修改进程内存 )