我有一些调试代码来验证数据结构的正确性和一些断言检查这个正确性,我只想在Debug构建中启用它:
{$ifdef DEBUG} function Sorted : Boolean; function LinearSearchByValue(const T : TType) : NativeInt; {$endif}
后来在一个方法中:
assert(Sorted);
例如.
在启用断言的调试版本中,一切都很好.但是,在我的Release版本中,如果禁用了断言,那么行断言(Sorted);导致编译器错误E2003 Undeclared标识符:’Sorted’.这是正确的,标识符未声明,但断言也被关闭,不应被评估或生成任何代码. (试图通过声明方法来欺骗断言但没有实现导致正常错误’不满意的前向或外部声明’.它显然也在寻找方法体.)
这导致了一些混乱的代码,其中必须声明Release版本中不应存在的方法并且具有正文,以便编译断开的断言.
如何在Delphi 2010中声明仅存在于调试版本中的方法,并在断言中使用那些也应仅存在于调试版本中的方法?
更多信息:
>我尝试用{$ifopt C}包装方法声明,检查断言是否已打开.对assert的调用仍然以’未声明的标识符’失败.
>编译器选项肯定是关闭断言. (我检查了 :))
>我已经尝试将调用包装调用到{$ifdef DEBUG}使用这些方法.但是,这很麻烦,不应该被要求.有一次,它让我担心即使在发布版本中也会编译断言,出于性能原因,我根本不需要它们. (这不会发生 – 不会生成断言代码.)
>我当前的策略是始终声明这些方法,但在Release构建中,如果方法体出来并用一个虚拟结果填充它.这里的目标是编译所有断言,但对方法的开销尽可能少,并且它们的返回值(如果它们在发布版本中实际上被调用)显然是错误的.
>在Delphi中是否有任何与C/C++风格的宏相当的东西,其中ASSERT(x)宏在发布版本中只是被定义为什么,导致编译器既不会看到也不关心断言中的语句?这是在C中使用宏的少数干净方式(IMO)之一.
因此,虽然没有生成断言,但它们是编译的.这回到我的问题:我如何最好地混合仅调试方法和断言,并发布版本?
不要从发布版本中排除代码.将代码保留在那里,并无条件地编译.反对让代码存在于发布版本中的论点是它“混乱”.但是你已经编写了代码,所以无论编译与否,它都会变得混乱.你也可以让编译器编译它;毕竟,编译额外的代码并不需要花费更长的时间.
试图排除与断言相关的代码只会通过要求条件编译指令使代码变得更加混乱.
断言和调试信息是正交设置.如果没有调试,则可以启用断言,反之亦然.
另一种方法是将与断言相关的代码移动到单元测试中.然后它们会自动从您的应用程序的所有版本中排除,但它们仍可用于测试.