SOCKET句柄泄露带来的内存灾难

Posted 资深研发的随笔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SOCKET句柄泄露带来的内存灾难相关的知识,希望对你有一定的参考价值。

前些时候游戏莫名其妙出现大量内存泄露,我感到很诧异,当然一般情况下游戏的内存管理是极其严苛的,出现如此大量的内存泄露到底是怎么回事?

句柄滥用导致的内存泄露会多夸张呢,尤其SOCKET,在某些客户端系统下,短短5个小时可以吃掉5GB以上内存,有甚者达到6GB,并且进程内存查看非常完好,并无激增,那内存去哪了?看看我们的排错过程。

 

排错过程:

1、首先我们第一反应还是内存泄露,但是观察进程发现占用非常合理,并没有丝毫的激增情况,甚至运行周期后还会出现下降的情况,此类情况用资源管理器和性能管理器可以进行排错,从而进一步确定不是游戏本身所申请的内存泄露。

这里包含 MALLOC,NEW等方式。

为了安全期间,采用VLD进行内存泄露排错,预计结果和我猜测的一样,并无激增或泄露。

此处步骤必须,用于排除激增或可能存在激增的内存问题,在LINUX下有其他库请自己查找,至于此地由于是客户端泄露,采用的VLD库用于内存泄露排错。

2、其次我们发现是系统在申请并归属于该进程的一块内存区域,就像共享内存一样,此时已经初步认定为句柄未释放导致的内存泄露,那么如何定位?

首先要让内存产生泄露,然后请出PCHunter,启动后找到游戏目标进程,右键查看进程句柄。

此时可以看到句柄数已经非常异常,数量高达1182个之多,有些进程甚至过万,这是明显的异常,除非一般的服务端进程,通常情况下句柄数不会达到如此之数。

然后要定位是什么句柄导致的系统内存激增,通过数量分析发现有一项神奇过多:

File \Device\Afd 0x00000B38 0xFFFFE0005183E070 30 32758

此处的 \Device\Afd  为关键,该类型代表为SOCKET句柄,此处已经彻底定位到原因,是SOCKET创建句柄但未释放导致的异常。

3、以上方法已经定位到基本错误,确定是SOCKET,但是怎么知道是哪里呢,这就要监控所有SOCKET创建的地方,我这里是因为使用了第一个第三方的PING库,而这个库代码只创建SOCKET不关闭SOCKET。

所以产生以上问题,简单解决只要关闭不使用SOCKET即可解决,重点在于定位是异常难的,所以特写此文。

以上是关于SOCKET句柄泄露带来的内存灾难的主要内容,如果未能解决你的问题,请参考以下文章

Netty Socket实时行情导致内存泄露的一种情况

socket中shutdown和closesocket的区别

netty 堆外内存泄露排查盛宴

记一次Netty堆外内存泄露排查过程

netty-socketio堆外内存泄露排查盛宴

Socket TCP Server一个端口可以有多少个长连接?受到什么影响?linux最大文件句柄数量总结