Delphi 对象在主程序中崩溃,但在移动到单元时不会崩溃

Delphi 对象在主程序中崩溃,但在移动到单元时不会崩溃,delphi,pascal,freepascal,Delphi,Pascal,Freepascal,我已经编写了一个自定义SDL GUI工具包(源代码已打开),但继承的对象存在问题 当对象位于主程序内时,不会调用构造函数,因此程序不会正确初始化对象,并且在执行某些命令后会崩溃(具体而言,TStartGameButton继承自GUI\u Canvas继承自GUI\u元素,而GUI\u元素中未定义的任何内容都会导致程序崩溃,并导致eaccessinvalition)。当对象放置在一个单元中时,这个问题就消失了 我知道我可以把它留在单元中,但它会导致一些丑陋的代码,希望可以避免 有人知道为什么会发生

我已经编写了一个自定义SDL GUI工具包(源代码已打开),但继承的对象存在问题

当对象位于主程序内时,不会调用构造函数,因此程序不会正确初始化对象,并且在执行某些命令后会崩溃(具体而言,TStartGameButton继承自GUI\u Canvas继承自GUI\u元素,而GUI\u元素中未定义的任何内容都会导致程序崩溃,并导致eaccessinvalition)。当对象放置在一个单元中时,这个问题就消失了

我知道我可以把它留在单元中,但它会导致一些丑陋的代码,希望可以避免


有人知道为什么会发生这种情况,以及我如何避免这种情况吗?

为什么要为所有对象提供单独的命名构造函数,而不是使它们成为虚拟的

  type   tx = object
                constructor init; virtual;
                end;
         txx = object(tx)
                   constructor init; virtual; // like override in Delphi classes.
                  end;
如果您需要查看视觉层次结构,请查看自由视觉,它几乎展示了TP对象模型的每个方面


很明显,在TP模型中,OOP虚拟构造函数是不可能的。自从Delphi2发布以来,旧式的Delphi对象已经被打破,可能更早。当它们具有编译器管理类型的字段(如
string
或动态数组)时,它们的继承性不好。2004年,在comp.lang.pascal.delphi.misc上有。下面是复制它的代码:

type
  TBase = object
  public
    s: string;
  end;

  TDerived = object(TBase)
  end;

procedure test;
var
  obj: TDerived; //okay for TBase!
begin
  assert(obj.s = '', 'uninitialized dynamic variable');
end;
事实上,由于函数的序言代码是如何生成的,所以只有在意外情况下才可以使用
TBase
。在该函数中添加额外的代码可能会使其崩溃

事实上,正如您所观察到的,旧式对象无法正确初始化。它们的字符串字段一开始并不包含空字符串;相反,它们包含垃圾,因此如果不使用类似于
FillChar
的东西,甚至不可能自己初始化它们

这似乎是由于变量是局部变量。单位范围(“全局”)变量似乎工作正常。在单元范围内声明但仅由单元的初始化部分使用的变量,或在程序范围内声明且仅在DPR文件的主开始-结束块中使用的变量,被编译器视为局部变量,因此它们不会像其全局对应项一样设置为所有零位。当您将变量声明移动到一个单元,但继续在DPR文件中使用它时,它将提升到“全局”状态


您的
TGUI\u元素
类型有一个名为
DbgName
string
成员,它看起来是类型层次结构中唯一的字符串字段。拿出它,或者把它改成
ShortString
,我敢打赌你的崩溃至少会暂时消失。

整个档案在tstartgamebutton上不会消失。嗯,这里的FPC似乎是错误兼容的,这里没有看到obj的初始化是的-把它改成ShortString修复了问题。非常感谢。具有讽刺意味的是,帮助我调试的函数是导致它崩溃的原因……主要是因为我不知道我可以:SShould this working?我将所有内容都更改为虚拟构造函数,并得到以下结果:错误:虚拟构造函数仅在类对象modelNo,Lochok中受支持,它不应该工作。编译器是正确的。虚拟构造函数仅在可以通过引用引用类型时才有用,但这仅适用于类,而不适用于旧式对象。