delphi:Exception EInvalidPointer in module Project1.exe

时间:2021-11-14 18:37:04

在用delphi XE5编程时遇到如下问题:

Exception EInvalidPointer in module Project1.exe at 00007595.

Invalid pointer operation.

delphi:Exception EInvalidPointer in module Project1.exe

从描述上来看,是指针使用错误引起的。我并没用使用太多指针变量,我首先检查了一下动态数组(事实上动态数组在SetLength后,即使越界了,也不会报错),发现没有问题。于是我是用Debug调试。出现如下窗口:

delphi:Exception EInvalidPointer in module Project1.exe

点击 Break,跳到了这里:

1 procedure TObject.FreeInstance;
2 begin
3   CleanupInstance;
4   _FreeMem(Pointer(Self));
5 end;

箭头指向第四行。

图片如下:

delphi:Exception EInvalidPointer in module Project1.exe

看到FreeMem,我想到自己创建过一个TFont类的一个对象。

代码如下:

 1 Ofont:=TFont.Create();
 2   OFont:=Canvas.Font;
 3   Canvas.Font.Name:='微软雅黑';
 4   Canvas.Font.Style:=[fsBold];
 5   Canvas.Font.Color:=clBlack;
 6   Canvas.Font.Height:=40;
 7   tempint:=(Form1.ClientWidth-Canvas.TextWidth('XXXXXXXX') ) div 2;
 8   Canvas.TextOut(tempint,3,'XXXXXXXX');
 9   Canvas.Font:=OFont;
10   OFont.Free;

然后我将第10行的语句注释掉后,异常就消失了。果然问题出在这。

但是新的问题又来了,一个对象创建了难道不应该Free吗?在百度上查了一番后,才知道:

使用这种方式创建对象,

   Ofont:=TFont.Create(); 

可以不Free,函数执行完后,会自行Free。不过最好Free。而且最好使用try语句。但是我这里为什么不能Free呢?

其实是一个关于对象复制的知识我没有搞懂。对象名,就是一个指针。使用:

   OFont:=Canvas.Font; 

其实是将Canvas.Font的指针赋值给了OFont,

  OFont.Free; 

这个语句实际上也在释放Canvas.Font。Canvas.Font是由系统管理的,这里不应该释放,否者就出现已释放的指针再进行释放。

我这段代码也没有起到“保护现场”的作用。应该使用:

 1 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:=40;
  tempint:=(Form1.ClientWidth-Canvas.TextWidth('XXXXXXXX') ) div 2;
  Canvas.TextOut(tempint,3,'XXXXXXXX');
  Canvas.Font.Assign(OFont);        //恢复为原始值
  OFont.Free;
end;