我有一个大型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
Run Code Online (Sandbox Code Playgroud)
我希望有人见过这个.问题的要素可能包括:
该代码包含许多奇怪的编译器指令,如{$ REALCOMPATIBILITY ON}和{$ H - }/{$ H +}指令,代码中有数千个{$ H +}/{$ H-}指令.
其次,代码使用了很多{$ I INCLUDE}指令,我怀疑包含文件可能会直接搞乱编译器的行编号.
我无法肯定地说,但我怀疑所有这些旧的"让它像turbo pascal for DOS"编译器开关是背后的原因.我想知道是否有人肯定知道这件事.它只发生在代码中的某些地方,并且项目有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.
Run Code Online (Sandbox Code Playgroud)
更新2:如果您需要扫描仪/修复程序来解决此问题,可以在此处下载我的(带源代码). 链接是Google云端硬盘.您可以从链接中查看源代码,但单击"文件"下拉菜单(谷歌驱动器Web用户界面的一部分),然后单击"下载"进行下载.
Mas*_*ler 22
我以前见过这样的东西,而IME通常是由于计算行数时的编译器错误.如果你在某些点上有非标准的换行符(不是CRLF) - 这可能发生 - IDE会做正确的换行符,但编译器不会将它们计为新行,所以之后的所有内容都会被一个抛出.
当我遇到这样的文件时,我在EditPad中打开它,将所有换行符转换为其他样式(Unix或Mac样式),然后将所有换行符转换为Windows样式并保存.这样可以确保文件中的每一行都以CRLF结尾,并且在重建之后,没有正确排列的蓝点的问题就会消失.
这是由不匹配的线路终端字符引起的常见问题.(行末尾缺少CR或LF的代码.)也可能是因为.dcu与编辑器中打开的源文件不匹配.
首先,最简单的解决方法是在常规文本编辑器(如记事本)中打开源文件.进行一些小改动(插入一个空行然后删除它),然后保存文件.记事本将修复行结尾.
如果这不是问题,请在IDE的搜索路径中查找可能位于驱动器上的.dcu(或.pas)文件的额外副本.有时,编译器会看到与编辑器中打开的版本不同的版本.