我写了一个类。这个类包含一个 TObjectList
这个 TObjectList 包含了一组对象的集合类只有些简单的功能、添加、清空等。
清空时我的代码如下:
procedure TColorCodeTable.Clear;
var i:Longint;
begin
for i := 0 to m_List.Count -1 do
begin
m_List.Items[i].Free;
end; m_List.Clear;
end;我的思路是:先 Free 所有对象 再把 m_List 中所有无效的对象引用清空。
但程序执行到 m_List.Clear; 时出错。是一个读写无效内存的错误。
跟踪代码发现:执行循环之后这个 List 就无效了。反复检查代码没有发现任何错误。
不解。各位大侠
是哪里出错了。附:增加过程的代码
procedure TColorCodeTable.Add(Obj: TColorCode);
begin
m_List.Add(Obj);
end;
这个 TObjectList 包含了一组对象的集合类只有些简单的功能、添加、清空等。
清空时我的代码如下:
procedure TColorCodeTable.Clear;
var i:Longint;
begin
for i := 0 to m_List.Count -1 do
begin
m_List.Items[i].Free;
end; m_List.Clear;
end;我的思路是:先 Free 所有对象 再把 m_List 中所有无效的对象引用清空。
但程序执行到 m_List.Clear; 时出错。是一个读写无效内存的错误。
跟踪代码发现:执行循环之后这个 List 就无效了。反复检查代码没有发现任何错误。
不解。各位大侠
是哪里出错了。附:增加过程的代码
procedure TColorCodeTable.Add(Obj: TColorCode);
begin
m_List.Add(Obj);
end;
当 Object 从队列中移出时,Object 就释放了;
你上面的代码有很多问题!你想释放某一个Object的时候,只需:m_List.Delete[i];
全部释放:m_List.Clear;
var i:Longint;
begin
m_List.OwnsObjects:=false;
for i := 0 to m_List.Count -1 do
begin
m_List.Items[i].Free;
end; m_List.Clear;
end;
其实m_List.OwnsObjects:=True
m_List.Clear;
就可以实现自动free
var i:Longint;
begin
for i := 0 to m_List.Count -1 do
begin
m_List.Items[i].Free; // 队列中的对象已经释放,但是还保存着对象指针
end; m_List.Clear; // 队列中的对象已经释放,所以这里肯定出错!
end;
var
i:Longint;
begin
for i := m_List.Count - 1 downto 0 do
begin
m_List.Items[i].Free;
m_List.Delete(i);
end;
end;
begin
if OwnsObjects then
if Action = lnDeleted then
TObject(Ptr).Free;
inherited Notify(Ptr, Action);
end;在接到删除lnDeleted这个Action之后,就会Free掉。所以你逐个将Object都Free之后,再Clear就有问题了。也就是说,如上面一位仁兄所讲。如果不设置OwnsObjects只Delete就够了。因为默认的OwnsObjects为True。constructor TObjectList.Create;
begin
inherited Create;
FOwnsObjects := True;
end;
procedure TColorCodeTable.Clear;
var
i:Longint;
begin
for i := m_List.Count - 1 downto 0 do
begin
m_List.Delete(i);
end;
end;
begin
SetCount(0);
SetCapacity(0);
end;procedure TList.SetCapacity(NewCapacity: Integer);
begin
if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
Error(@SListCapacityError, NewCapacity);
if NewCapacity <> FCapacity then
begin
ReallocMem(FList, NewCapacity * SizeOf(Pointer));
FCapacity := NewCapacity;
end;
end;procedure TList.SetCount(NewCount: Integer);
var
I: Integer;
begin
if (NewCount < 0) or (NewCount > MaxListSize) then
Error(@SListCountError, NewCount);
if NewCount > FCapacity then
SetCapacity(NewCount);
if NewCount > FCount then
FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Pointer), 0)
else
for I := FCount - 1 downto NewCount do
Delete(I);
FCount := NewCount;
end;所以说Clear,仅仅是把容量数量设为0,没有触动Notify,并发送lnDelete去释放每一个Item。所以还得遍历删除一遍。
错了 如果你的item对应相应的对象的指针,应该这样调用Objecttype(M_List.Items[i]).Destroy;这样才能保证对象正确的释放 要不他指的另一个地址或者地址错误 如果幸运你会释放 但大多数都不会幸运 运行时错误是必然的
Delete(I);是我的失误。就用Clear来清空。可以结贴了。
是这个
procedure TObjectList.Notify(Ptr: Pointer; Action: TListNotification);
begin
if OwnsObjects then
if Action = lnDeleted then
TObject(Ptr).Free;
inherited Notify(Ptr, Action);
end;OwnsObjects 默认为 true 的。
释放是可以让它给我完成多谢各位