我使用的是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 当然会执行优化。但是,它不会执行
SecureZeroMemory
函数旨在规避的优化。 Delphi中不需要使用该函数;只需使用普通的旧ZeroMemory
,甚至FillChar
。它们不是宏,并且它们不会执行任何 Delphi 认为是可以优化的未使用赋值语句的操作。
Delphi 默认执行代码优化,您可以在 Project > Options > Compiler 中禁用它。
Delphi 帮助提供了一些关于使用哪种类型的优化的提示:
$O 指令控制代码优化。在{$O+}状态下,编译器会执行许多代码优化,例如将变量放入CPU寄存器、消除公共子表达式以及生成归纳变量。
它还指出 “编译器不会执行“不安全”优化”,但从某种意义上说,它们不会改变执行路径,而不是从安全角度来看。
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 中的等效项)。
我不相信编译器会消除这样明显的死代码。 我从来没有在代码上设置断点时遇到过麻烦,这些断点本来可以作为冗余而被消除。
对于某些场景,编译器可以检测代码是否不可达并消除该代码。
例如,编译器正确地消除了下面代码中“无法访问”的部分。
它不会为该行生成代码,因此:
刚刚在 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;
--杰罗恩