首页 文章

当对象被销毁时,Delphi对象字段中的动态数组是否会被自动释放/释放?

提问于
浏览
1

如果我有一个包含带动态数组的字段的Delphi对象(包含例如字符串),如下所示:

TClassWithDynArrayField = class(TObject)
   public
      some_dyn_array : array of string;
   end;

当对象被销毁时,这个数组(和/或它的内容)会被自动释放/释放,还是我必须在对象的析构函数中以某种方式显式地完成它以避免内存泄漏或其他讨厌(垃圾中的崩溃)字符串和动态数组的收集器,或其他堆相关的代码等)?

如果答案是肯定的,那么一旦对象被销毁就会自动解除定位,同时也不会对字符串/动态数组垃圾收集产生任何不一致性,对于多级动态数组字段也是如此吗?例如这样:

TClassWithMultiLevelDynArrayField = class(TObject)
   public
      some_multi_level_dyn_array : array of array of string;
   end;

如果我改为使用定义这些数组(单级和/或多级)的“通用”方式(从我所听到的内部等同于“非通用”定义),答案是否会有任何不同动态数组,或不是吗?),如下:

TClassWithGenericMultiLevelDynArrayField = class(TObject)
   public
      some_generic_multi_level_dyn_array : TArray<TArray<string>>;
   end;

注意:对于所有这些示例,请假设其他代码将在对象被销毁之前随意填充所有级别的数组 .

我问这个的原因是我在对象(和动态分配的记录)中使用动态数组时经常会出现奇怪的访问冲突,并且the Delphi reference page about System.Finalize中有一些半相关的谈话,似乎区分了动态的自动释放数组和例如字符串(即在基于Dispose的解除分配的情况下,但我认为它也可以应用于对象字段?),如下所示:

Finalize只应在Delphi代码中使用,其中动态分配的变量通过除Dispose过程之外的其他方式释放 . 动态数组永远不能使用Dispose过程释放,但可以通过将它们传递给Finalize来释放 . 对于使用Dispose释放的全局变量,局部变量,对象和动态变量,编译器会生成代码,以在销毁实例时最终确定变量包含的所有长字符串,变量和接口 . 如果动态变量满足以下两个条件,则需要调用Finalize以在变量可以被释放之前完成变量 . 该变量通过除Dispose标准过程之外的其他方式释放(例如,使用FreeMem) . 该变量包含长字符串,变体或接口,并非所有字符串都是空的或未分配的 . Finalize只是将所有长字符串设置为空,并将所有变量和接口设置为Unassigned,从而正确释放由长字符串和变体引用的任何内存 .

请注意,在提到字符串的情况下,从未提及动态数组,并且在第一句中,动态数组被称为某种“手动”特殊情况?

因此,当对象被破坏时,Delphi对象的字段中的动态数组将被自动解除分配/释放,无论它们如何填充,例如字符串,无论它们是否是任意多个“级别深度”(即动态数组中的动态数组),如上面的例子中所示?

1 回答

  • 5

    是的,动态数组字段的处理方式就像长字符串和其他编译器管理的变量一样,无论现在多层次都是如此 .

    它们的引用计数将在对象的析构函数中递减,如果计数为零,则将释放该数组 .

相关问题