HeQing博客之家

.Net、Delphi、VC技术交流

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

        无论是用Delphi还是VC编写的程序,内存泄漏始终是一个令每个程序员头痛的问题,特别是一个大型的服务器系统,内存泄漏更会对系统的长期稳定运行造成致命的硬伤,往往系统是很正常的运行几天后才出现问题。而内存泄漏也是一个极难以发现的BUG。笔者在Delphi中开发一个数采服务器时就出现过这种情况,当数采服务器运行时,从Win2000的“任务管理器”中能明显看出该进程所占内存在不断的增大,直致该进行崩溃。笔者花了很长的时间才发现了问题所在,原来是由于笔者直接对结构体的Pointer指针进行释放操作引出的内存泄漏。为此作者将问题分析如下,以免诸位再步我后尘。

    以下为该内存泄漏的重现代码,为了说明问题,笔者删除了无关代码行:

PDataItem =^TDataItem;
TDataItem 
= Record
  .
  .
  .
  strData: String;
end;

lstDataItems: TList;
pItem: PDataItem;

lstDataItems :
= TList.Create;

new(pItem); // 分配了一个结构体的内存
lstDataIetms.Add(pItem); // 存入列表中
  .
  . 
// 自己的事务处理代码
  .

// 然后函数结束时释放分配的内存
for i := 0 to lstDataItems.Count-1 do
  Dispose(lstDataItems.Items[i]);

    你能看出问题所在吗?对了,Dispose(lstDataItems.Items[i]) 语句会引起内存泄漏,lstDataItems.Items[i]返回的是一个Pointer类型的数据,Dispose函数对Pointer类型数据释放内存时,只会释放该指针所指向的内存块。如上代码所示,Pointer指向的是一个结构体TDataItem,那么,该结构体所本身所占的内存块就被释放了,但是,如果该结构体内部的数据成员如果为String类型、PChar、或对象时,这些数据成员自身所占用的内存会得不到释放,从而引起内存泄漏。显而易见,以上代码至少会引strData数据成员的内部内存泄漏。

    从上例可见,在释放一个指针的内存时,为Dispose函数传递一个明确的数据类型是必要的,而为了贪图方便直接传递Pointer指针,有可能会出现内存泄漏,上例正确的代码应该这样的:

// 然后函数结束时释放分配的内存
for i := 0 to lstDataItems.Count-1 do
begin
  pItem :
= lstDataItems.Items[i];
  Dispose(pItem);
end;

    当然,如果结构体中包含有PChar类型、结构体指针或其类似的数据成员,则你必须在释放该结构指针之前保证这些成员的私有内存得到合理释放,或在其他地方能够能到合理释放,否则也会引起内存泄漏。

 

 

posted on 2004-10-14 20:48  HeQing博客之家  阅读(1194)  评论(0编辑  收藏  举报