内存问题。(50分)

  • 主题发起人 主题发起人 qqjm
  • 开始时间 开始时间
Q

qqjm

Unregistered / Unconfirmed
GUEST, unregistred user!
写了一个做为缓冲的类,当设置缓冲的数量超过2800条时,在释放对象时程序会弹出“Access violation at address 0040510c in module 'project1.exe'. write of address 0103FFFC”的错误,执行第二次才能成功,十分不解。是Delphi的内存管理问题还是我设计的问题?

TSmsMsgItem=record
....
_SmsLists:Array of TSmsMsgItem; //sizeof(TSmsMsgItem)=352
.....
constructor TSmsMsgList.Create(iMinCount: integer);
begin
  getMem(self._SmsLists ,iMinCount*sizeof(TSmsMsgItem));
end;

destructor TSmsMsgList.Destroy;
begin
FreeMem(self._SmsLists);
inherited ; //到这里出错,但是如果少于2900则没问题!
end;
 
_SmsLists:Array of TSmsMsgItem;
说明你的_SmsLists是动态数组。那么Delphi动态数组的释放是生存期自管理的。
分配的时候直接SetLength(),释放的时候可以直接赋值给Nil就行了。

动态数组是使用引用计数生存期自管理的。内存分布为
darray = record
refcount:LongInt;//引用计数
Count:LongInt; //总数
Data:array[0..Count-1] of 类型; //数据
end;
当我们赋值的时候动态数组不会立刻复制一份。而是仅仅修改指针,增加引用计数。当我们做修改的时候才会重新复制一份拷贝,并修改。原来的数据引用计数减一。减到0就释放。

你的方式只要用一个_SmsLists:=nil;就减少了引用计数。你就不用管了。
如果是New和DisPose分配释放的话连_SmsLists:=nil;都可以省略。New/DisPose直接支持生存期自管理。
GetMem、FreeMem释放的时候可以把生存期自管理的类型(动态数组,长字符串,接口等)全部给Nil再释放。
也可以用Borland的标准方式GetMem->Finalize->FreeMem就可以把全部生存期自管理的部分全部释放掉。
再具体一点的话可以去看Delphi内存分配释放部分的帮助。说的很清楚。
 
接受答案了.
 
后退
顶部