【问题标题】:Delphi Cast: Memory leak?Delphi Cast:内存泄漏?
【发布时间】:2015-07-08 16:24:27
【问题描述】:

在 Delphi 中,我正在从已经创建的基类中转换一个继承类。我相信这在两个类之间共享基类地址,但是继承的类的额外成员获得分配给它们的额外内存,但没有初始化。

如果共享基类随后被释放,这是否会导致 Inherited 类的成员发生内存泄漏?

如果是这样,如果我想保持基类不变,那么清理继承类成员的最佳方法是什么?

program Project1;

uses
  SysUtils;

type
   TBase = class(TObject)
   public
     basemember : string ;
     Constructor Create() ;
   end;

   TInherited = class(TBase)
   public
     inheritedmember : string ;
     Constructor Create() ;
   end ;

   Constructor TBase.Create() ;
   begin
       basemember := 'Basemember' ;
       Writeln ('basemember') ;
   end ;

   Constructor TInherited.Create() ;
   begin
       inheritedmember := 'inheritedmember' ;
       Writeln ('inheritedmember') ;
   end ;

var
     baseclass      : TBase;
     castbaseclass  : TInherited;
begin

  Writeln ('Base Class');
  baseclass := TBase.Create();

  Writeln ('');
  Writeln ('Cast Inherited Class');
  castbaseclass := TInherited(baseclass);

  baseclass.Free; //memory leak?
  ReadLn;

end.

【问题讨论】:

    标签: delphi memory-leaks


    【解决方案1】:

    这里没有内存泄漏,但转换仍然是错误的。

    你关心这行代码:

    castbaseclass := TInherited(baseclass);
    

    由于 Delphi 类是引用类型,baseclasscastbaseclass 都是指针。您在这里所做的一切都被分配了一个指针变量。您以后再也不会参考castbaseclass。如果你这样做了,那么就有可能出现运行时错误,因为编译器认为 castbaseclass 是一个 TInherited 实例,但实际上它是一个不太专业的类 TBase 的实例。

    但是,你有一个很深的误解。

    我正在从已经创建的基类中转换一个继承类。我相信这会在两个类之间共享基类地址,但是继承的类的额外成员会获得分配给它们的额外内存,但不会被初始化。

    不!绝对不。为了实例化TInherited 实例,您必须调用TInherited 的构造函数。您不能创建一个类的实例并期望它会演变成另一个类。实例的类型在创建时一劳永逸地确定。实例的内存是在创建实例时分配的,而不是其他时间。

    所以,如果您想要TInherited,请创建一个。如果您想要TBase,请创建一个。但是您不能创建TBase 并将其类型更改为TInherited。您可以做的是创建一个TInherited,然后将其分配给TBase 类型的变量。那是因为TInherited 派生自TBase

    所以你可以写:

    var
      base: TBase;
      inherited_: TInherited; // _ because inherited is a keyword
    ....
    inherited_ := TInherited.Create;
    base := inherited_;
    

    但你不能写:

    var
      base: TBase;
      inherited_: TInherited;
    ....
    base := TBase.Create;
    inherited_ := base;
    

    【讨论】:

    • 我猜要分配继承的成员变量,继承的类必须用'new'创建 - 但是有没有办法让继承类的基本组件指向一个已经存在的基类实例?
    • 两个分数都没有。您通过调用构造函数而不是通过调用 new 来分配类的实例。不,您不能将一个实例叠加到另一个实例上。好吧,理论上可以通过某种形式的自定义实例分配来实现。但这将是疯狂和不切实际的。也许我什至不应该提到这一点!
    • 你显然对所有这些都有一个非常错误的心智模型。我建议您花点时间纠正这种心理模型。
    • TInherited.Create ctor 也应该有一个 Inherited 调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多