码迷,mamicode.com
首页 > 其他好文 > 详细

珍惜每一滴水(kbmmw 中的内存调试)

时间:2016-06-04 14:50:48      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:

    作为一个服务器端的应用,最基本的要求就是稳定,当然要做一个稳定的服务器端,需要涉及到很多方面,

内存泄露就是稳定的一个致命杀手,因为服务器的物理内存是有限的,即使一个功能有很小的内存泄露,经过

长时间的运行,也会累积成一个非常大的内存泄露,导致服务器内存耗尽,系统崩溃。因此珍惜服务器资源是

开发者必须重视的(当然了,对于内存无法管理的语言及框架,那就算了)。

   最新版的kbmmw 中加入了内存调试功能,这个功能不但可以应用在kbmmw 服务器中,你也可以在其他程序中

使用。

  其实自从delphi 2007 开始,delphi 就默认使用FastMM 作为内存管理器,FastMM 也自带了内存泄露报告功能。

但是FastMM只能追踪通过GetMem 分配的内存资源,无法追踪windows其他方式分配的内存(Virtual/Heap/Global/Local).

 另外,即使你屏蔽了FastMM 的内存泄露报告,kbmmw 的内存调试器可以在应用中的任何时间来记录内存的使用情况。

我们要使用kbmmw 的内存调试功能,先做一下准备工作。

首先我们要打开 kbmmwconfig.inc 加入


{$DEFINE KBMMW_SUPPORT_DEBUGMEMORY}
{$DEFINE KBMMW_INSTALL_DEBUGMEMORY_HANDLERS}

这两句条件编译,以便激活kbmmw 的内存调试功能,默认是关闭的,如图。

技术分享

如果没有 {$DEFINE KBMMW_SUPPORT_DEBUGMEMORY} 这一句,内存调试不起作用。

如果没有 {$DEFINE KBMMW_INSTALL_DEBUGMEMORY_HANDLERS},内存追踪不起作用。

 

现在就可以在你的程序里面 加入kbmMWDebugMemory 单元了,你的程序就有了内存调试功能了。

技术分享

 

kbmmw 自动的勾住了 delphi 程序中所有的内存分配功能,包括以前的borlandMM, 和windows 自己的Virtualxxx, Globalxxx,

Localxxx and Heapxxx 这些函数。当然了,也完美支持Fastmm 的内存管理器。

kbmmw 为每次的内存分配和内存再分配都用一个唯一的自增64位 数来标记。通过这个数字,我们可以追踪在某个时间段中内存分配

的情况,这些点叫checkpoints.原理上,一个checkpoint 就是一个64位的数字,通过这些数字我们可以追踪每次的内存分配情况。

kbmmw 同时维护着一个分配的内存及分配次数的统计表。你可以任何时候来查阅这个统计表

 

procedure TForm1.Timer1Timer(Sender: TObject);
begin
     lLiveAllocationsCount.Caption:=inttostr(TkbmMWDebugMemory.LiveAllocationCount)+ (+inttostr(TkbmMWDebugMemory.LiveAllocationCountPerSec)+/sec);
     lLiveAllocSize.Caption:=inttostr(TkbmMWDebugMemory.LiveAllocationSize)+ (+inttostr(TkbmMWDebugMemory.LiveAllocationSizePerSec)+/sec);
     lMaxAllocationCount.Caption:=inttostr(TkbmMWDebugMemory.MaxAllocationCount);
     lMaxAllocationSize.Caption:=inttostr(TkbmMWDebugMemory.MaxAllocationSize);
     lMaxCapacity.Caption:=inttostr(TkbmMWDebugMemory.CurrentAllocationCountCapacity);
     lCheckPoint.Caption:=inttostr(FCheckPoint);
     lGCCount.Caption:=inttostr(TkbmMWDebugMemory.AllocationKeys.GCCount);
end;

 

 其中:

   LiveAllocationCount 是当然使用的、活动着的内存。它包括所有的 (Borland- object/string/memory, Localmemory, Globalmemory, Virtualmemory, Heapmemory).

  其它参数的作用请参考kbmmw 的源代码(没有源代码?那就买一份呗)。

知道了内存分配情况,那么接下来就是如何在程序结束后检测内存泄露了。

什么时候内存泄露?

就是被分配的内存,永远没有被释放。

有些内存泄露无所谓,因为其在整个应用过程中只发生一次,有点像定义了一个全局变量,这种泄漏时是可预测的,而且不随时间的增长而增长,这类泄露在delphi

的RTL 和VCL 中有很多,我们无法消灭它们,也没必要消灭它们(对于爱干、鱼儿的这些强迫症患者简直就是噩梦)。

对于那些每次执行都发生的内存泄露,随着时间的增长越来越多,耗尽系统资源,到最后导致系统崩溃。因此这种泄露我们必须消灭。

因为内存追踪无法了解一个人(我不是指“竹子”)的想法,因此在程序运行过程中,无法确定一块主动分配的内存是否真的需要释放?因此只有在程序退出时,

我们才能知道这些内存确实需要释放,然而并没有释放。所以只有在程序退出时,才能确定内存是否泄漏?

在kbmmw 里面,我们可以在尽可能早的地方把内存检测加入。

TkbmMWDebugMemory.ReportDestination(c:\temp\leaks.txt); 
TkbmMWDebugMemory.ReportLeaksOnShutdown:=true; 
TkbmMWDebugMemory.StartLeakChecking; 

我们可以做一个明显的泄漏,测试一下

procedure TForm1.Button8Click(Sender: TObject);
var
   sl:Tstringlist;
begin

  sl:=Tstringlist.Create;
end;

运行程序,执行以上代码,然后退出。

就会显示以下提示:

技术分享

如果我们去看leaks.txt

就会很明显的发现这个问题。

技术分享

以上信息有时很精确,有时不一定准确,主要依靠你程序编译时的一些设置,尤其是优化代码很厉害的话,会差异很大。

当然了,内存使用情况和调试涉及的东西很多,如果你要进一步深入的话,可以看kbmmw 的源码和例子。

 

有一点需要说明,以上所有的操作都是有代价的,如果在正式生产环境中使用,尽量不要启用内存调试功能。

只有出现内存泄露时,才建议使用以上功能发现泄露原因,消灭掉泄漏后,立即关闭调试功能。

 

珍惜每一滴水(kbmmw 中的内存调试)

标签:

原文地址:http://www.cnblogs.com/xalion/p/5558577.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!