我正在尝试调试仅在我的大型应用程序 - 在XE3中正常工作 - 在使用XE4编译后运行时才出现的行为。该问题似乎导致一些引用的字符串(例如“MyString”)即使在由Web.HTTPProd中的TPageProducer“解除引用”之后仍保留其引号。例如,请考虑以下代码,该代码是此Delphi源代码单元Web.HTTPApp的小摘录:
procedure ExtractHeaderFields(Separators, _WhiteSpace: TSysCharSet; Content: PChar;
Strings: TStrings; Decode: Boolean; StripQuotes: Boolean = False);
{$ENDIF NEXTGEN}
var
Head, Tail: PChar;
EOS, InQuote, LeadQuote: Boolean;
QuoteChar: Char;
ExtractedField: string;
{$IFNDEF NEXTGEN}
WhiteSpaceWithCRLF: TSysCharSet;
SeparatorsWithCRLF: TSysCharSet;
{$ENDIF !NEXTGEN}
function DoStripQuotes(const S: string): string;
var
I: Integer;
InStripQuote: Boolean;
StripQuoteChar: Char;
begin
Result := S;
InStripQuote := False;
StripQuoteChar := #0;
if StripQuotes then
begin
for I := Result.Length - 1 downto 0 do
if Result.Chars[I].IsInArray(['''', '"']) then
if InStripQuote and (StripQuoteChar = Result.Chars[I]) then
begin
Result.Remove(I, 1);
InStripQuote := False;
end
else if not InStripQuote then
begin
StripQuoteChar := Result.Chars[I];
InStripQuote := True;
Result.Remove(I, 1);
end
end;
end;
当我使用TPageProducer时,我看到这个被调用,我可以看到我的好源代码字符串进入上面的ExtractHeaderFields例程,然后进入'DoStripQuotes'函数。进入DoStripQuotes并观察'Result'表明它不会改变,即使调用Result.Remove(剥离引号)也是如此。当我把这个'DoStripQuotes'例程带到一个简单的测试应用程序时,它不会编译,告诉我'Result.anything'是不允许的。我假设那个结果,虽然它被定义为'string'必须是Web.HTTPProd上下文中的另一种类型的字符串。
所以我想到这可能与我听过的'不变的字符串'有关。我读到了SO question关于这一点,虽然我得到了要点,但我可以提供更实用的建议。
具体来说,我想回答以下问题:
感谢您的帮助。
稍后编辑:如下面接受的答案中所述,这是VCL单元Web.HTTPApp.pas中的一个错误,它应该在2645行的两个地方读取“Result:= Result.Remove(I,1)”而不是“Result.Remove(I,1)”
答案 0 :(得分:9)
如果允许使用表示法Result.Length,那么什么类型的'字符串'是'结果'?
自string
以来您使用的UnicodeString
,别名为Delphi 2009
。不同之处在于此代码使用新的记录助手(特别是SysUtils.TStringHelper
)。这就是让你在字符串变量上使用.
表示法的原因。
有没有一种方法可以告诉编译器为一个单元使用'XE3'兼容性?
没有。有问题的代码是一个库单元,它被设计为以特定模式编译。更重要的是,除非你自己编译RTL / VCL,否则你不能轻易地重新编译它。即使有这样的模式,也没有用,因为代码完全错误(见下文)。没有多少模式切换可以修复这段特定的代码。
我开始想到这可能与我听说过的不可变字符串有关。
不是。没有任何Delphi编译器具有不可变的字符串。不可变字符串的概念只是作为未来变化浮现的东西。如果进行了更改,则希望首先在移动编译器中进行更改。
问题实际上只是您发布的代码中的一个相当简单的错误,显然根本没有测试。使用Remove
是错误的。该方法不会就地修改字符串。相反,它返回一个删除了字符的新字符串。代码应为:
Result := Result.Remove(I, 1);
编码ExtractHeaderFields
的开发人员犯了这个错误的原因是谁设计了错误地命名为Remove
方法的字符串帮助程序代码。由于Remove
是一个动词,你可以期望它就地运作。如此方法不会修改主题并返回新实例的方法应该被赋予名词。因此,此方法应命名为Remnants
。在我看来,好像RTL设计师复制了同样存在缺陷的.net命名。
如果QC报告尚不存在,您应该提交。我知道XE4 update 1刚刚发布。它包含一个修复程序似乎是合理的。
我认为你的其他选择是:
Web.HTTPApp
单元的副本,并自行修复错误。