在用delphi XE5编程时遇到如下问题:
Exception EInvalidPointer in module Project1.exe at 00007595.
Invalid pointer operation.
从描述上来看,是指针使用错误引起的。我并没用使用太多指针变量,我首先检查了一下动态数组(事实上动态数组在SetLength后,即使越界了,也不会报错),发现没有问题。于是我是用Debug调试。出现如下窗口:
点击 Break,跳到了这里:
procedure TObject.FreeInstance;
begin
CleanupInstance;
_FreeMem(Pointer(Self));
end;
箭头指向第四行。
图片如下:
看到FreeMem,我想到自己创建过一个TFont类的一个对象。
代码如下:
Ofont:=TFont.Create();
OFont:=Canvas.Font;
Canvas.Font.Name:='微软雅黑';
Canvas.Font.Style:=[fsBold];
Canvas.Font.Color:=clBlack;
Canvas.Font.Height:=;
tempint:=(Form1.ClientWidth-Canvas.TextWidth('XXXXXXXX') ) div ;
Canvas.TextOut(tempint,,'XXXXXXXX');
Canvas.Font:=OFont;
OFont.Free;
然后我将第10行的语句注释掉后,异常就消失了。果然问题出在这。
但是新的问题又来了,一个对象创建了难道不应该Free吗?在百度上查了一番后,才知道:
使用这种方式创建对象,
Ofont:=TFont.Create();
可以不Free,函数执行完后,会自行Free。不过最好Free。而且最好使用try语句。但是我这里为什么不能Free呢?
其实是一个关于对象复制的知识我没有搞懂。对象名,就是一个指针。使用:
OFont:=Canvas.Font;
其实是将Canvas.Font的指针赋值给了OFont,
OFont.Free;
这个语句实际上也在释放Canvas.Font。Canvas.Font是由系统管理的,这里不应该释放,否者就出现已释放的指针再进行释放。
我这段代码也没有起到“保护现场”的作用。应该使用:
Ofont.Assign(Canvas.Font); //将原始值保留
来复制对象的值来达到保护现场的作用。代码修改后如下:
procedure TForm1.InitFormUI();
{*功能:在窗体上方居中显示 “XXXXXXXX”}
var
tempint:integer;
Ofont:TFont;
begin
{* Ofont不添加 free语句,程序异常消失 -
*异常为:(delphi Exception EAccessVioation in module Project1)}
Ofont:=TFont.Create();
Ofont.Assign(Canvas.Font); //将原始值保留
Canvas.Font.Name:='微软雅黑';
Canvas.Font.Style:=[fsBold];
Canvas.Font.Color:=clBlack;
Canvas.Font.Height:=;
tempint:=(Form1.ClientWidth-Canvas.TextWidth('XXXXXXXX') ) div ;
Canvas.TextOut(tempint,,'XXXXXXXX');
Canvas.Font.Assign(OFont); //恢复为原始值
OFont.Free;
end;