Delphi: 在Create()构造函数结束时发生访问冲突错误

9
我有一个非常基本和简单的类,就像这样:
单位装载器;
interface

uses
  Vcl.Dialogs;

type
  TLoader = Class(TObject)
  published
      constructor Create();
  end;

implementation

{ TLoader }    
constructor TLoader.Create;
begin
   ShowMessage('ok');

end;

end.

在Form1中,我这样调用它:
procedure TForm1.Button1Click(Sender: TObject);
var
 the : TLoader;
begin
  the := the.Create;
end;

现在,在the := the.Create部分之后,Delphi会显示带有'ok'的消息,然后给出一个错误,并说Project Project1.exe raised exception class $C0000005 with message 'access violation at 0x0040559d: read of address 0xffffffe4'.

同时它还显示了这一行:

constructor TLoader.Create;
begin
   ShowMessage('ok');

end; // <-------- THIS LINE IS MARKED AFTER THE ERROR.

我是 Delphi 的新手。我正在使用 Delphi XE2,但我无法解决这个错误。有人能给我指点迷津或者有解决方案吗?

1
我不知道 var instance: TLoader 应该做什么。你确定你需要那个全局变量吗?看起来你打算声明本地的 TLoader 变量。 - Andreas Rejbrand
1
@xangr 我的评论并不是针对你的。这是一个明显的重复问题。我相信我已经回答过它不止一次了。我相信Andreas和Mason也是如此。但我无法快速找到一个问题来说明这一点。Stack Overflow的搜索功能并不是很好,但我怀疑这是一个非常困难的问题。 - David Heffernan
2
很难找到这个问题的重复,@David,因为通常很难泛化地提出这个问题。我们已经看到了许多潜在问题的实例,但每次都是以“调试我的代码”问题的形式呈现,因为这是从不知道问题所在的人的角度来表达问题的唯一方式。 - Rob Kennedy
1
Xangr,编译器没有警告你正在使用未初始化的变量吗? - Rob Kennedy
@RobKennedy 不是的 :( 只有在那部分出现访问冲突错误。或者我错过了,但我确定没有像你提到的那样的错误。 - xangr
显示剩余3条评论
2个回答

18
var
  the : TLoader;
begin
  the := the.Create;

这是不正确的。应该是

var
  the : TLoader;
begin
  the := TLoader.Create;

我应该睡几个小时 :( 怎么会错过那个点!谢谢问题已解决!谢谢 :) - xangr
2
@xangr - 别担心,这是 Delphi 经典问题。我已经做过无数次了,都习以为常了。 - Martin James
你应该使用 the.ClassType().Create(); :-)))) PS. @Martin 我认为你也应该调用 *inherited;*。这很烦人,但这会让你在未来重构 Delphi RTL 核心和自己的代码时更加自如。 - Arioch 'The
5
@Arioch,不行。ClassType 函数的工作原理是从给定对象中读取类引用。在你的建议中,ClassType 将从一个未初始化的变量中读取,因为还没有有效的对象引用,这与原始问题面临的问题相同。ClassType 是实例方法,所以你需要有一个实例。 - Rob Kennedy
@RobKennedy 嗯,是的。我应该考虑到虚拟构造函数 :-) 这样的快捷方式在C++中可能有效,但Delphi太灵活了,不允许这样做 :-) - Arioch 'The
4
@Arioch,你在说什么?虚拟构造函数与此无关。ClassType函数在C++ Builder和Delphi中的工作方式相同;在未初始化的the变量上使用表达式the->ClassType()与在Delphi中一样是错误的,在C++中也是错误的。你认为这是一个快捷方式,但在C++中,直接调用ClassType返回的构造函数时会出错;不能正常工作的代码不是快捷方式。 - Rob Kennedy

7
您的语法错误。如果您正在构造一个新对象,应该在构造函数调用中使用类名而不是变量名:
procedure TForm1.Button1Click(Sender: TObject);
var
 the : TLoader;
begin
  the := TLoader.Create;
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接