出现Access violation at address 0070d872 in module 'XXXX.EXE'. Read of address FFF

  • 主题发起人 主题发起人 zhaolibo
  • 开始时间 开始时间
Z

zhaolibo

Unregistered / Unconfirmed
GUEST, unregistred user!
出现Access violation at address 0070d872 in module 'XXXX.EXE'. Read of address FFFFFFFF.(100分)<br />遍历组件,是Tpanel就销毁,然后创建一个新的,执行第一次的时候没问题,执行第二次就出现如题目所示的错误提示,不知是为什么?代码如下:
try
for m:=0 to componentcount-1 do
begin
if (Components[m] is Tpanel) then
begin
(components[m] as Tpanel).Free;
break;
end;
except
end;
p:=Tpanel.Create(frmdelr2);
p.Parent:=frmdelr2;
p.Left:=464;
p.Width:=335;
p.Top:=0;
p.Height:=553;
 
p:=Tpanel.Create(frmdelr2);
应该是这句有错误吧,连续两次创建P当然出错啦。
 
楼上误导了,p创建两次没有问题,顶多造成内存泄漏,出现错误的原因是Panel释放的时候没有使用RemoveControl把他从窗口的控件列表中删除,导致第二次执行时窗口中实际有两个控件指针,而其中一个已经为空指针了。
另外,象代码中这样从列表中逐个删除或者释放一个项目,是不能这么写的,你想啊,你先删除了第一个,那第二个就变成第一个了,第三个就变成第二个了,依次类推,所以无论项目是否为空,最终都会发生异常。
 
(components[m] as Tpanel).Free;
(components[m] as Tpanel) := Nil;
 
我记得控件释放的时候,是可以自动Remove的。所以楼上的解释可能有问题。
 
to Wolfding:
听你一讲恍然大悟,应该就是这么回事,可又不是很清楚应该怎么做,能否帮我把代码改一下呀,解决了问题我好赶快撤,不在这丢人,顺便把分送上[:D]
 
to 李翔鹏:
(components[m] as Tpanel) := Nil;
这句不能执行
 
TControl在释放的时候,会调用
SetParent(nil);
所以,Parent会释放他

楼主的真正问题,我看是可能出在frmdelr2指针上,楼主并没有交代这个指针是干嘛的,我用Self指针代替,就没有问题。
 
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;

type
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
Button2: TButton;
Panel2: TPanel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
m: Integer;
P: TPanel;
L, T, W, H: Integer;
begin
for m := 0 to componentcount-1 do
if (Components[m] is Tpanel) then
try
P := Tpanel(components[m]);
L := P.Left;
T := P.Top;
W := P.Width;
H := P.Height;
P.Free;
P := nil;
break;
except
end;
p := Tpanel.Create(Self);
p.Parent := Self;
p.Left := L;
p.Width := W;
p.Top := T;
p.Height := H;
end;
end.
//以上是我写的测试代码我按了N次不出现问题啊
 
不大记得清楚了,可能应该是RemoveControl的时候控件是可以释放的,机器上没有装delphi所以不能给你调试,你循环里这么写自己试试吧:
var
iCount: Integer;
Panel: TPanel;
begin
iCount := ComponentCount;
for i := 0 to iCount - 1 do
begin
Panel := TPanel(Components[iCount - i -1]);
RemoveControl(Panel);//是用Panel调用还是用i调用你试试看
Panel.Free; // 如果这句报错说明上一句中它已经被释放了,那就把这句去掉
end;
......................
end;
 
//楼上不用去担心那个了,看下面就知道了
destructor TComponent.Destroy;
begin
Destroying;
if FFreeNotifies &lt;&gt; nil then
begin
while Assigned(FFreeNotifies) and (FFreeNotifies.Count &gt; 0) do
TComponent(FFreeNotifies[FFreeNotifies.Count - 1]).Notification(Self, opRemove);
FreeAndNil(FFreeNotifies);
end;
DestroyComponents;
if FOwner &lt;&gt; nil then FOwner.RemoveComponent(Self); //这句就是拉
inherited Destroy;
end;
 
不好意思呀各位,是我说得不清不楚,实际上只执行我给出的这段代码是没有问题的,执行多少次都可,我是在执行一次后,再向Tpanel里添加和删除一些组件,再回头执行,就会报错,可能的原因在哪里呀?
 
再向Tpanel里添加和删除一些组件 你的代码呢??
 
procedure TForm1.Button1Click(Sender: TObject);
var
m: Integer;
P: TPanel;
L, T, W, H: Integer;
btn: TButton;
begin
for m := 0 to componentcount-1 do
if (Components[m] is Tpanel) then
try
P := Tpanel(components[m]);
L := P.Left;
T := P.Top;
W := P.Width;
H := P.Height;
P.Free;
P := nil;
break;
except
end;
p := Tpanel.Create(Self);
p.Parent := Self;
p.Left := L;
p.Width := W;
p.Top := T;
p.Height := H;
btn := TButton.Create(P);
btn.Parent := P;
btn.Left := 10;
btn.Top := 10;
btn.Width := 160;
btn.Height := 50;
btn.Caption := '你是测试按钮';
end;
//又添加了组件了,也没有问题啊
 
找不出规律,有时出有时不出
 
后退
顶部