内存泄漏

  • 正常情况内存消耗比较平稳,但是异常后如下图可以看到内存在几个小时内内存消耗殆尽导致操作系统直接kill掉srs进程

排查难点

  • 内存泄漏是偶发的这是排查的难点,如果是必现可以借助一些成熟的工具比如:Valgrind,memleak, mtrace等等可以很容易定位到问题,并且这些工具网上有铺天盖地的文档,也很容易使用,这里不再赘述。

排查过程

使用工具排查

  • 不知道具体原因的情况下所以首先还是使用Valgrind和memleak等成熟的工具排查但是并没有发现明显的内存泄漏问题,放弃使用。

分析内存镜像

分析core文件

  • gdb attach {pid}

  • 执行(gdb)gcore命令dump生成core文件,注意会短暂的夯死主进程。

  • pmap {pid}获取内存分布情况如下图可以看到内存占用比较大的heap区,也可以通过cat /proc/{pid}/maps查看内存分布但是不如pmap直观的看到虚拟内存的分布情况。

  • 用gdb打开core文件,将0000000005c2b000起始的内存内容输出到文件中

  • gdb -c {core文件} {your_application}

  • (gdb)set height 0

  • (gdb)set logging on

  • (gdb) x/612205568a 0x0000000005c2b000

  • x/612205568a 格式说明:

    • 612205568=4782856*1024/8 (因为是64 bit所以要/8byte)

    • a为gdb输出其中一种格式(可以参看gdb x现象内存数据根式说明) https://blog.csdn.net/yasi_xi/article/details/9263955

    • 最后就是分析上面生成的gdb.txt

    • 直接看不好看所以格式化一下cat gdb.txt|c++filt >demo.txt 可以看到就是srs的class类了

    • 通过统计demo.txt 中各个对象的个数来判断是否是该对象存在内存泄漏,存在比较多个对象有可能是内存泄漏点,当然也有可能实际上你的程序就是这么多正常的对象,所以需要理智的判断。

      • cat demo.txt|awk ‘BEGIN{stat[""]=0}{stat[$5]++}END{for(i in stat) print i"="stat[i]}’
    • 通过以上方式确实发现内存泄漏问题,SrsStatisticStream对象在内存中比较多,但是结合代码分析泄漏对象占用的内存比较小,不可能在几个小时内耗尽5G内存,分析结果不符合线上的情况。

分析现象结合业务场景提出猜测

  • 根据内存泄漏的现象,首先想到的是可能因为某个流造成的问题
  • 结合现象发现内存消耗比较严重,可能是内存中存在音视频包造成的问题。
  • 结合srs源码和占内存比较多的业务场景,有2个地方比较耗内存
    • gop cache但是碰到keyframe后会清理之前缓存的音视频包,应该不是这个问题。
    • flv回源会有一个SrsMessageQueue存放音视频包,但有shrink的逻辑会释放内存,只有一种情况会占用内存那就是不发生shrink同时dts回退回造成内存泄漏(有可能)因为下行cdn回源可以存在网络问题,第三方流有可能存在dts回退的情况。
    • 模拟flv回源卡顿,同时让dts回退确实内存会暴涨,猜测是该问题,要是能找到线上内存中的SrsMessageQueue对象会进一步确认问题,带着问题继续分析coredump文件。

虚拟内存分布

c++虚函数表

  • 多态的实现原理
  • 通过demo学习一下虚函数表
#include <iostream>
using namespace std;
class A
{
public:int i=20001111; //16进制为1313157virtual void func() {}virtual void func2() {}
};
class B : public A
{public:int j=10001111;//16进制为989ad7void func();
};void B::func()
{cout<<"===B==="<<endl;
}int main()
{cout << sizeof(A) << ", " << sizeof(B); B* b=new B();b->func();return 0;
}
  • 通过gdb设置断点调试以上简单程序

    • 编译g++ -g -o demo demo.cpp

    • gdb demo

    • 断点调试输出b指针

    • 获取B对象this指针(堆地址)通过p命令获取整个B对象

    • 通过以上可以知道vtable地址就是this指针

接着分析core文件

  • 有了以上知识铺垫,可以很容易分析heap内存获取SrsMessageQueue对象
  • core文件比较大怎么快速获取对象
    • gdb支持python脚本解析
    • 参考https://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html#Python-API
    • python脚本如下heap.py
import gdb, traceback;
class heap(gdb.Command):def __init__(self):super(heap, self).__init__("all-heap", gdb.COMMAND_DATA)def invoke(self, arg, from_tty):try: # 从以上pmap可以找到比较大的堆内存的起始地址为0x0000000005c2b000next = "0x0000000005c2b000";while True:#name1 = gdb.execute('x/2xa %s' % (next), to_string=True)#print('name2 %s' % (name1))name = gdb.execute('x/2xa %s'%(next), to_string=True).split('\t')[1].strip()#print('name: %s,%s' % (name,next))if name.find('SrsMessageQueue') >0 :print('SrsMessageQueue find %s'%(next))print('SrsMessageQueue find ======%s' % (gdb.execute('x/2xa %s'%(next), to_string=True)))next = gdb.parse_and_eval('%s + 16' % (next)).__str__()except gdb.error:print("error")returnheap()
- (gdb) source heap.py
- (gdb) all-heap
- 通过脚本获取SrsMessageQueue对象this指针

 通过SrsMessageQueue->SrsConnection->SrsConsumer->SrsSource->SrsRequest找到出问题流Id

解决

  • 问题已经定位原因是flv拉流卡顿,同时源流发生dts回退造成音视频包在内存堆积
  • 解决

总结

  • Valgrind,memleak, mtrace等工具解决内存泄漏,如果可以复现可以很好定位,如果偶发的情况没有用武之地。
  • 偶发内存泄漏问题还是需结合业务场景分析源代码找出问题。

收获

  • 了解了内存布局,以及对c++虚函数表的理解。

参考

  • http://c.biancheng.net/view/267.html
  • https://blog.csdn.net/weixin_31563557/article/details/112432300

使用gdb分析coredump文件排查流媒体服务srs偶发内存泄漏问题相关推荐

  1. Linux内核: 分析coredump文件

    Linux内核:分析coredump文件 - 内核代码崩溃 分类:             Linux内核编程             2013-10-23 17:21     619人阅读     ...

  2. GDB调试CoreDump文件

    GDB调试CoreDump文件 Author:onceday date:2022年8月1日 1.引言 当进程收到某些信号时,默认的信号处理函数在终止进程之前会对进程的内存映像进行存储,形成当前时刻的& ...

  3. gdb 提示 coredump 文件 truncated 问题排查

    本文选自"字节跳动基础架构实践"系列文章. "字节跳动基础架构实践"系列文章是由字节跳动基础架构部门各技术团队及专家倾力打造的技术干货内容,和大家分享团队在基础 ...

  4. 排查 Node.js 服务内存泄漏,没想到竟是它?

    背景 团队最近将两个项目迁移至 degg 2.0 中,两个项目均出现比较严重的内存泄漏问题,此处以本人维护的埋点服务为例进行排查.服务上线后内存增长如下图,其中红框为 degg 2.0 线上运行的时间 ...

  5. Go使用Delve 分析CoreDump文件定位错误

    CoreDump是异常退出程序的内存快照.可以用在进程死后debug来找出crash发生的原因以及牵连的变量. 通过GOTRACEBACK,Go提供了控制程序崩溃时的输出.变量还可以强制生成CoreD ...

  6. WinDbg分析dump文件排查bug

    文章:WinDbg-如何抓取dump文件 命令: cd C:\Windows\System32\inetsrv appcmd list wp 可以查看各个站点的pid 转载于:https://www. ...

  7. Linux调试——gdb调试器的简单使用调试coredump文件

    文章目录 一.背景 二.gdb的指令与使用 1.gdb的基本指令. 2.gdb指令的简单使用 1.进入gdb模式 2.实例说明 三.调试coredump文件 前提:本质上是在调试程序崩溃之后的内存镜像 ...

  8. coredump gdb 调试_gdb 调试coredump文件过程

    gdb 调试coredump文件过程: 第一步:首先需要一个进程的coredump文件,怎么搞出coredump文件呢? 1. ps -fax|grep                 进程名称 找到 ...

  9. coredump文件是如何生成的

    目录 一.coredump 文件生成过程 二.coredump文件生成原理 1. 信号处理 do_signal() 2. 生成 coredump 文件 三.生产环境应该打开 coredump 功能吗? ...

最新文章

  1. cad 怎么显示块句柄_新手必看的CAD小技巧,老师傅精选汇总,三分钟教你学习用处多多...
  2. 损失函数的意义和作用_哈佛CASTER | 基于化学子结构表征预测药物相互作用
  3. python网络编程例子
  4. tcpdump的简单选项介绍
  5. excel调用python编程-使用python集合进行EXCEL数据分析
  6. linux服务器同时运行两个或多个tomcat
  7. 避障机器人程序c语言,基于51单片机小车寻迹、避障源程序(注释很详细)
  8. 10分钟看懂, Java NIO 底层原理
  9. 单例模式中的属性实现
  10. python函数返回none_Python 函数默认返回None的原因
  11. unity3d 随机物体生成器 工具
  12. Magento 获取当前货币和货币符How to get current currency in Magento
  13. php trace 图形,PHP Trace 设计原理
  14. php当前完整url的写法
  15. Veeam 全面助力等保2.0/ 云数据管理解决方案/ 医疗行业最佳实践
  16. php new mpdf,php – PDF不合并大于使用mPDF的PDF-1.5版本
  17. dijkstra algorithm example
  18. 54部经典国外动画片---送给70-80年代的朋友
  19. HP服务器远程管理工具iLO详细介绍
  20. 利用lasso回归建立预测模型并绘制列线图 二分类结局资料的lasso回归与列线图绘制

热门文章

  1. python矩阵和向量乘积_向量点积和矩阵乘积的区别
  2. 数据库关键字作为字段如何处理
  3. 第三节课,学习C语言的第三天
  4. 超分辨率重建——(一)何为超分和分类
  5. php实现九宫格连线,小程序之页面用九宫格及item跳转的功能实现
  6. python实现Pyecharts实现动态地图(Map、Geo)
  7. 手把手教你仿一个知乎日报Android客户端(一)多图
  8. 还单身?不如来看看脱单神器!
  9. H5游戏开发之抓住小恐龙
  10. Kolla部署Pike版本的OpenStack-allinone