在用delphi XE5編程時遇到如下問題:
Exception EInvalidPointer in module Project1.exe at 00007595.
Invalid pointer operation.

從描述上來看,是指針使用錯誤引起的。我並沒用使用太多指針變量,我首先檢查了一下動態數組(事實上動態數組在SetLength后,即使越界了,也不會報錯),發現沒有問題。於是我是用Debug調試。出現如下窗口:

點擊 Break,跳到了這里:
1 procedure TObject.FreeInstance; 2 begin 3 CleanupInstance; 4 _FreeMem(Pointer(Self)); 5 end;
箭頭指向第四行。
圖片如下:

看到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;
