输入的常量可以成为内存泄漏的来源吗?

时间:2015-12-07 13:15:36

标签: delphi constants typed

各种来源似乎都不鼓励使用类型常量来支持更多面向对象的技术。例如DelphiBasics,其中描述为"非常奇怪"和StackOverflow Question提供了一些关于它们可能被使用的背景信息。以下是true和typed常量的示例。

const
  RESULTS_BASIC1        = $01;  // True constant
  RESULTS_BASIC2: BYTE  = $01;  // Typed constant

我正在使用Delphi 7和FastMM4,并且正在报告单个TCriticalSection的泄漏。在项目选项中启用详细的地图文件后,FastMM4堆栈跟踪显示如下:

402E58 [StConst][StConst][@GetMem]
40454B [WinConvert][WinConvert][d_len]
404926 [Main][Main][EXAMPLE_TYPED_CONSTANT1]
...

如果我然后删除键入的常量,则报告相同的TCriticalSection泄漏...在下一个类型的常量上!在减慢了一个接一个地删除一个类型的常数之后,我仍然没有接近" true"泄漏的来源。

两个相关问题:

1)类型化常量(实际上是带有内存地址的变量)是否可能成为内存泄漏的真正来源? FastMM4可以报告错误的泄漏吗?

2)是否应该避免输入常量?如果是,建议的替代方案是什么?例如,假设我使用经过处理器的TickCount(无符号32位整数):

dwElapsed := (GetTickCount() - m_dwLastFlashCheck);
if (dwElapsed > 2000) then
    begin
    m_dwLastFlashCheck := GetTickCount();
    DoSomething();
    end;

定义一个"常数"似乎很自然。如:

RATE_FLASH: DWORD   = 2000;
// ...
if (dwElapsed > RATE_FLASH) then
// etc

1 个答案:

答案 0 :(得分:4)

这些常量位于可执行映像中。因此,它们在模块加载时分配,在模块卸载时解除分配,因此不会泄漏。

你的常数不是问题。你显然有一个解码不当的堆栈跟踪。例如,如果您可以使用madExcept来解码堆栈跟踪,那么我怀疑您会获得更好的堆栈跟踪。错误的堆栈跟踪也是由于过时的映射文件造成的,这也是合理的。

最重要的是,您不应该将数据地址作为堆栈上的返回地址。因此,堆栈跟踪必须是错误的。

现在,您还链接到建议不要使用类型化常量的引用。但是你错误地阅读了这些参考文献。在许多情况下,键入的常量是一种非常有效的方法。

有问题的是可分配类型的常量 - 任何名称为矛盾的特征都应该被认为是极度怀疑。事实证明,可分配的类型常量只存在于实现事故中。当引入类型常量时,它们不能放在只读存储器中,因为当时的系统不支持内存保护。引入内存保护时,编译器得到增强,支持两种类型的常量:只读和可分配。请执行shun assignable typed常量,但只读类型常量非常合理。