Delphi编译器是否执行优化?

问题描述 投票:0回答:5

我使用的是Delphi 7 IDE。 Delphi 编译器是否会优化代码,就像 C++ 编译器在以下链接中所做的那样?

http://msdn.microsoft.com/en-us/library/aa366877(VS.85).aspx

WCHAR szPassword[MAX_PATH];
// Retrieve the password
if (GetPasswordFromUser(szPassword, MAX_PATH))    
   UsePassword(szPassword);
// Clear the password from memory
SecureZeroMemory(szPassword, sizeof(szPassword));

如果在此示例中调用

ZeroMemory
而不是
SecureZeroMemory
,编译器可以优化该调用,因为
szPassword
缓冲区在超出范围之前不会被读取。密码将保留在应用程序堆栈中,可以在故障转储中捕获或被恶意应用程序探测。

delphi optimization compiler-optimization
5个回答
12
投票

是的,Delphi 当然会执行优化。但是,它不会执行

SecureZeroMemory
函数旨在规避的优化。 Delphi中不需要使用该函数;只需使用普通的旧
ZeroMemory
,甚至
FillChar
。它们不是宏,并且它们不会执行任何 Delphi 认为是可以优化的未使用赋值语句的操作。


3
投票

Delphi 默认执行代码优化,您可以在 Project > Options > Compiler 中禁用它。

Delphi 帮助提供了一些关于使用哪种类型的优化的提示:

$O 指令控制代码优化。在{$O+}状态下,编译器会执行许多代码优化,例如将变量放入CPU寄存器、消除公共子表达式以及生成归纳变量。

它还指出 “编译器不会执行“不安全”优化”,但从某种意义上说,它们不会改变执行路径,而不是从安全角度来看。


1
投票

Delphi 确实优化了代码(它是一个现代的、优秀的编译器)。优化删除行的另一个例子是:

SomeFunction();  // Set breakpoint here, then step (F10)
myInt := 7;      // Next line will not hit this...
myInt := 13;     // ...but will instead skip to here

我喜欢通过在项目中的每个 .pas 文件中添加

{$I MyProjectOptions.inc}
来确保优化处于正确的状态(而不是意外地打开或关闭)。它位于单位名称的正下方(位于文件的顶部)。在“MyProjectOptions.inc”中,您只需添加以下代码:

// Is this a debug or non-debug build?
{$IF Defined(DEBUG)}
    {$O-}   // Turn optimization off
{$ELSEIF Defined(NDEBUG)}
    {$O+}   // Ensure optimisation is on
{$IFEND}

最后,确保您已在项目 > 选项 > Diectories/Conditionals 的条件定义部分中定义了“DEBUG”和“NDEBUG”(或旧版本 Delphi 中的等效项)。


0
投票

我不相信编译器会消除这样明显的死代码。 我从来没有在代码上设置断点时遇到过麻烦,这些断点本来可以作为冗余而被消除。


0
投票

对于某些场景,编译器可以检测代码是否不可达并消除该代码。

例如,编译器正确地消除了下面代码中“无法访问”的部分。
它不会为该行生成代码,因此:

  1. 所以没有蓝色项目符号表明有代码
  2. 放置在该行上的断点将在视觉上标记为“无法到达”

刚刚在 Delphi XE 中进行了测试,但较旧的 Delphi 版本也有类似的行为。

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

procedure Test;
begin
  if (True = False) then
    Writeln('Unreachable')
  else
    Writeln('Reachable');
end;

begin
  try
    Test();
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

需要相当长的时间才能了解代码级别和喜欢者级别的优化器何时(或何时不)启动。

例如:当你开启优化时,编译器也会在不使用变量时立即消除它们。
有时,它甚至消除了全局符号。 Danny Thorpe(前 Delphi 编译器工程师和首席科学家)曾经写过一个神奇方法 Touch 来防止这种情况。
只需在方法末尾调用此 Touch 方法即可在调试期间欺骗优化器:

procedure Touch(var arg);
begin
end;

--杰罗恩

© www.soinside.com 2019 - 2024. All rights reserved.