Delphi 数据类型太大:柏林更新 2 中超过 2 GB
Delphi Data type too large: exceeds 2 GB in Berlin Update 2
我有一个装置可以同时用于 Delphi 和 Lazarus。在 Lazarus 中编译的单元没有任何异常,但在 Delphi 中它给我错误数据类型太大:超过 2 GB。下面是代码:
unit UType;
{$ifdef FPC}
{$MODE delphi}{$H+}
{$endif}
interface
type
TFreqType = Extended;
TFreqCutArray = Array [0..0]of TFreqType;
PFreqCutArray = ^TFreqCutArray;
FilterOrder = Integer;
TAS_Sample = Extended;
TAS_SampleArray = Array[0..High(Integer) div Sizeof(TAS_Sample) - 1] of TAS_Sample;
PTAS_SampleArray = ^TAS_SampleArray;
TAS_Float = Extended;
TComplex = record
Re, Im: TAS_Sample; // Z = Re + i*Im
end;
PComplex = ^TComplex;
TComplexArray = Array[0..High(Integer) div Sizeof(TComplex) - 1] of TComplex;//here Delphi gives the error
PComplexArray = ^TComplexArray;
FilterProc = function(V: TAS_Sample): TAS_Sample of object;
implementation
end.
我正在使用 Berlin Update 2,在 Lazarus 中使用相同的代码编译没有任何错误。
这似乎是一个编译器缺陷。您可以这样声明类型:
TComplexArray = Array[0..67108862] of TComplex;
编译器将接受该声明。请注意 67108862 = High(Integer) div Sizeof(TComplex) - 1
.
您可以通过声明常量来避免对上限进行硬编码:
const
ComplexArrayUpperBound = High(Integer) div Sizeof(TComplex) - 1;
type
TComplexArray = Array[0..ComplexArrayUpperBound] of TComplex;
这种类型声明的风格现在已经很不流行了。我强烈建议您使用动态数组。这些将使您自动清理动态内存,并允许编译器为所有数组访问添加范围检查代码。后一点很重要,因为它会给您代码中边界错误的早期警告。
如果您不分配数组而是声明这些类型以启用数组索引,那么使用 {$POINTERMATH ON}
.
可能更简单
此外,我建议您使用 Double
而不是 Extended
。您不太可能需要 10 字节 Extended
类型,切换到 Double
将使您的内存需求减半。由于对齐,您的 TComplex
大小为 32 个字节,但基于 Double
的版本为 16 个字节。由于更好地使用缓存,这种节省将带来显着的性能优势。
这是一个编译得很好的旧声明:
PUserInfo0Arr = ^TUserInfo0Arr;
TUserInfo0Arr = array[0..MaxInt div SizeOf(TUserinfo0) - 1] of TUserinfo0;
我的代码中还剩下几十个,我现在更喜欢 Inc(PUserInfo0Arr)。
我有一个装置可以同时用于 Delphi 和 Lazarus。在 Lazarus 中编译的单元没有任何异常,但在 Delphi 中它给我错误数据类型太大:超过 2 GB。下面是代码:
unit UType;
{$ifdef FPC}
{$MODE delphi}{$H+}
{$endif}
interface
type
TFreqType = Extended;
TFreqCutArray = Array [0..0]of TFreqType;
PFreqCutArray = ^TFreqCutArray;
FilterOrder = Integer;
TAS_Sample = Extended;
TAS_SampleArray = Array[0..High(Integer) div Sizeof(TAS_Sample) - 1] of TAS_Sample;
PTAS_SampleArray = ^TAS_SampleArray;
TAS_Float = Extended;
TComplex = record
Re, Im: TAS_Sample; // Z = Re + i*Im
end;
PComplex = ^TComplex;
TComplexArray = Array[0..High(Integer) div Sizeof(TComplex) - 1] of TComplex;//here Delphi gives the error
PComplexArray = ^TComplexArray;
FilterProc = function(V: TAS_Sample): TAS_Sample of object;
implementation
end.
我正在使用 Berlin Update 2,在 Lazarus 中使用相同的代码编译没有任何错误。
这似乎是一个编译器缺陷。您可以这样声明类型:
TComplexArray = Array[0..67108862] of TComplex;
编译器将接受该声明。请注意 67108862 = High(Integer) div Sizeof(TComplex) - 1
.
您可以通过声明常量来避免对上限进行硬编码:
const
ComplexArrayUpperBound = High(Integer) div Sizeof(TComplex) - 1;
type
TComplexArray = Array[0..ComplexArrayUpperBound] of TComplex;
这种类型声明的风格现在已经很不流行了。我强烈建议您使用动态数组。这些将使您自动清理动态内存,并允许编译器为所有数组访问添加范围检查代码。后一点很重要,因为它会给您代码中边界错误的早期警告。
如果您不分配数组而是声明这些类型以启用数组索引,那么使用 {$POINTERMATH ON}
.
此外,我建议您使用 Double
而不是 Extended
。您不太可能需要 10 字节 Extended
类型,切换到 Double
将使您的内存需求减半。由于对齐,您的 TComplex
大小为 32 个字节,但基于 Double
的版本为 16 个字节。由于更好地使用缓存,这种节省将带来显着的性能优势。
这是一个编译得很好的旧声明:
PUserInfo0Arr = ^TUserInfo0Arr;
TUserInfo0Arr = array[0..MaxInt div SizeOf(TUserinfo0) - 1] of TUserinfo0;
我的代码中还剩下几十个,我现在更喜欢 Inc(PUserInfo0Arr)。