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

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

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

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

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

最新版的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 的源码和例子。

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

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

时间: 2024-10-17 12:32:21

珍惜每一滴水(kbmmw 中的内存调试)的相关文章

在指定时间干,必须干(kbmmw 中的事件调度)

从去年开始,kbmmw 慢慢增加内涵,除了完善各种服务外,陆续增加和扩展了作为一个中间件必须有的功能, 例如,权限管理.日志系统.调度系统.内存调试等功能. 今天给大家介绍一下kbmmw 的调度事件,调度事件的主要目标就是”在指定时间干,必须干“,不是“爱干”,是“必须干” :). 在传统的delphi 中事件调度室通过两种方式,一种方式通过Ttimer 来实现,(我20年做的母校的食堂餐饮消费系统就是通过Ttimer来轮询 POS 机的).另外一种就是通过扩展Tthread 线程类,通过后台完

在VC++中启用内存泄露检测

检测内存泄漏的主要工具是调试器和 CRT 调试堆函数.若要启用调试堆函数,请在程序中包括以下语句: #define CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h> 注意   #include 语句必须采用上文所示顺序.如果更改了顺序,所使用的函数可能无法正确工作. 通过包括 crtdbg.h,将 malloc 和 free 函数映射到其“Debug”版本 _malloc_dbg 和 _free_dbg,这些函数将跟踪内存

windows进程中的内存结构(好多API,而且VC最聪明)

在阅读本文之前,如果你连堆栈是什么多不知道的话,请先阅读文章后面的基础知识.   接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论.下文中的C语言代码如没有特别声明,默认都使用VC编译的release版.   首先,来了解一下 C 语言的变量是如何在内存分部的.C 语言有全局变量(Global).本地变量(Local),静态变量(Static).寄存器变量(Regeister).每种变量都

C语言内存调试技巧—C语言最大难点揭秘

本文将带您了解一些良好的和内存相关的编码实践,以将内存错误保持在控制范围内.内存错误是 C 和 C++ 编程的祸根:它们很普遍,认识其严重性已有二十多年,但始终没有彻底解决,它们可能严重影响应用程序,并且很少有开发团队对其制定明确的管理计划.但好消息是,它们并不怎么神秘.引言C 和 C++ 程序中的内存错误非常有害:它们很常见,并且可能导致严重的后果.来自计算机应急响应小组(请参见参考资料)和供应商的许多最严重的安全公告都是由简单的内存错误造成的.自从 70 年代末期以来,C 程序员就一直讨论此

YJX_Driver_033_驱动中的内存管理

1. 驱动中的内存管理 A. 物理内存 B. 虚拟内存 C. Ring0地址和Ring3地址 D. 驱动程序和进程的关系 E. 分页和非分页内存 F. 分配内核内存 [120]了解两个概念:物理内存  虚拟内存 [140]以下概念针对 32位Windows操作系统(32位及以上的CPU)(32位 / 64位 CPU) [210]64位下的这些概念 略有区别 [240] “ A.物理内存:(Physical Memory Address) 目前主流的操作系统还是32位的XP,而32位的系统提供的寻

【转】Android中的内存管理--不错不错,避免使用枚举类型

原文网址:http://android-performance.com/android/2014/02/17/android-manage-memory.html 本文内容翻译自:http://developer.android.com/training/articles/memory.html 随机存取存储器(RAM)再任何软件开发环境中都是宝贵的资源,但是在移动操作系统中,内存资源更为宝贵,使用时也会收到限制.虽然Android的Dalvik虚拟机有运行时的垃圾回收机制,但是这不意味着你的A

Android 中使用内存监测工具Heap,及内存分析工具 MAT

无论怎么小心,想完全避免bad code是不可能的,此时就需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的地方.Android tools中的DDMS就带有一个很不错的内存监测工具Heap(这里我使用eclipse的ADT插件,并以真机为例,在模拟器中的情况类似).用Heap监测应用进程使用内存情况的步骤如下: 1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的: 2. 将手机通过USB链接至电脑,链接时需要确认手机是处于“USB调试”模式

VS环境中进行内存泄漏的检测

根据MSDN中的介绍,亲测整理. 本篇比较长,如不愿花费太多时间,可只看第一段和第四段,甚至只看第四段. 内存泄漏,即未能正确释放以前分配的内存,是 C/C++ 应用程序中最难以捉摸也最难以检测到的 Bug 之一.借助 Visual Studio 调试器和 C 运行时 (CRT) 库,可以检测和识别内存泄漏.检测内存泄漏的主要工具是调试器和 C 运行库 (CRT) 调试堆函数. 简单的使用 要调用CRT调试堆函数,需包含头文件<crtdbg.h>. 在程序的退出点之前调用函数 _CrtDump

VS中检测内存泄漏的方法

vs中检测内存泄漏的方法 分类: MFC2013-03-08 21:44 2764人阅读 评论(0) 收藏 举报 使用vs的内存检测有以下几种方法. 在debug模式下以F5运行: 方法一: [html] view plaincopy #define CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> //在入口函数中包含 _CrtDumpMemoryLeaks(); //即可检测到内存泄露 //以如下测试函数为例: i