我在工作的大型 Delphi 代码库中遇到问题,作为从 Delphi 2007 移植到 XE2 的副作用,我们现在遇到以下奇怪的相关问题:
即使在调试版本中,您也无法设置断点或单步执行代码,因为行号完全混乱,仅在某些单元中。
在第 2010 行故意引入语法错误会导致光标聚焦在第 2020 行,给或取 3 或 4 行,如下所示:
.
procedure Correct;
begin
DoSomething; // syntax error reported HERE but the real error is below.
// more stuff here.
end;
procedure OllKorrect;
begin
ThisLineIsFine();
__VARIABLE_NOT_DEFINED__ := 1; // intentional error
end
我希望有人以前见过这个。问题的要素可能包括:
该代码包含许多奇怪的编译器指令,例如 {$REALCOMPATIBILITY ON} 和 {$H-}/{$H+} 指令,代码中有数千个 {$H+}/{$H-} 指令。
其次,代码使用了很多 {$I INCLUDE} 指令,我怀疑包含文件可能会直接弄乱编译器的行号。
我不能肯定地说,但我怀疑所有这些旧的“让它像 DOS 的 turbo pascal 一样工作”编译器开关是其背后的原因。我想知道是否有人肯定对此有所了解。它只发生在代码中的某些地方,并且对于一个拥有超过 500 个单元的项目,其中一些达到 10K/20KLOC 的大小,这绝对是令人沮丧的。我能说的是,不仅有 {$I include.inc} 指令的单元会搞砸,而且许多包含大量 {$H-}/{$H+} 或 {$REALCOMPATIBILITY} 指令的单元也会没有这个问题。如果我能看到行为不端的单位有什么共同点,我就能弄清楚这一点。
更新:线路终止问题是有道理的。我运行了检测到问题的代码。修复代码已被注释掉,因为如果您取消注释它并删除所有源代码,那就是您的问题。它将非 unicode 文件加载到 unicode TStringList 中并将其保存回来。这在我的世界里没问题,因为它的所有版本都受控和备份。你的旅费可能会改变。
program linefeedsProject1;
{$APPTYPE CONSOLE}
uses
IOUtils,
Classes,
Types,
SysUtils;
var
broken,notBroken:Integer;
function fix(filename:String):Boolean;
var
sl:TStringList;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(filename);
//TODO:Change file extensions.
sl.SaveToFile(filename);
finally
sl.Free;
end;
end;
function scan(filename:String):Boolean;
var
crFlag:Boolean;
lfFlag:Boolean;
missingCr:Integer;
missingLf:Integer;
f:TFileStream;
buf:Array[0..1024] of AnsiChar;
n:Integer;
procedure scanChars;
var
i:Integer;
begin
for i := 0 to n-1 do
begin
if buf[i]=#13 then
begin
crFlag := true;
lfFlag := false;
end
else if buf[i]=#10 then
begin
if not crFlag then
inc(missingCr);
lfFlag := true;
crFlag := false;
end
else begin
if (crFlag) then
inc(missingLf);
crFlag := false;
lfFlag := false;
end;
end;
end;
begin
result := false;
crFlag := false;
lfFlag := false;
missingCr := 0;
missingLf := 0;
f := TFileStream.Create(filename, fmOpenRead);
try
while f.Position< f.Size do
begin
n := f.Read(buf[0],1024);
scanChars;
end;
if (missingCr>0) or (missingLf>0) then
begin
WriteLn(' ', filename);
Inc(broken);
result := true;
end
else
begin
Inc(notBroken);
end
finally
f.Free;
end;
end;
var
files:TStringDynArray;
afile:String;
begin
try
broken := 0;
notBroken := 0;
files := TDirectory.GetFiles('C:\dev\abackupcopyofyoursourcecode', '*.pas',
TSearchOption.soTopDirectoryOnly );
// tried TSearchOption.soAllDirectories and it exploded. not recommended.
for afile in files do
begin
if scan(afile) then
begin
// fix(afile); // uncomment at your own risk and only on a backup copy of your code.
end;
end;
WriteLn('Broken ', broken);
WriteLn('not broken ',notBroken);
// readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
更新 2:如果你想要一个扫描仪/修复器来解决这个问题,你可以在这里下载我的(带有源代码)。 链接是 Google Drive。您可以从链接中查看源代码,但单击“文件”下拉菜单(Google Drive Web 用户界面的一部分),然后单击“下载”进行下载。