2013-06-12 74 views
8

我試圖調試只有當我的大型應用程序 - 在XE3中正常工作 - 纔在與XE4編譯後運行時出現的行爲。這個問題似乎導致一些帶引號的字符串(例如「MyString」)即使在Web.HTTPProd中被TPageProducer「取消引用」之後也能保留引號。例如,請考慮下面的代碼是從這個Delphi源單元Web.HTTPApp小摘錄:爲什麼TPageProducer不能從字符串中刪除引號?

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.Remove(去除引號)。當我將這個'DoStripQuotes'例程發佈到一個簡單的測試應用程序時,它不會編譯,告訴我'Result.anything'是不允許的。然後我假定Result,雖然它被定義爲'string',但它必須是Web.HTTPProd上下文中的另一種類型的字符串。

所以我開始想,也許這與我聽說過的'不可變字符串'有關。我讀了這個SO question,儘管我明白了,但我可以用更實際的建議來做。

具體來說,我想回答以下幾個問題:

  1. 如果符號Result.Length允許什麼類型的「字符串」的是「結果」?
  2. 有沒有一種方法可以讓編譯器使用'XE3'兼容性? (這可能會讓我看到問題的起源點)。我試過{$ ZEROBASEDSTRINGS ON/OFF),但這似乎導致了更多的混亂,我不知道我在做什麼!

感謝您的幫助。

後來編輯:正如在下面接受的答案中指出的那樣,這是VCL單元Web.HTTPApp.pas中的一個錯誤,它應該在2645行周圍的兩個地方讀取「Result:= Result.Remove(I,1)」,不是「Result.Remove(I,1)」

回答

9

如果允許使用符號Result.Length,什麼類型的'string'是'Result'?

這只是同樣的老string,別名爲UnicodeString,你一直以來Delphi 2009使用。區別在於這段代碼使用了新的記錄幫助程序(特別是SysUtils.TStringHelper)。這就是你可以在字符串變量上使用.表示法。

有沒有一種方法可以告訴編譯器在單元中使用'XE3'兼容性?

號有問題的代碼是一個庫單元和它被設計成在特定的模式下進行編譯。更重要的是,除非您自己編譯RTL/VCL,否則不能輕易重新編譯它。即使有這樣的模式,它也無濟於事,因爲代碼完全是錯誤的(見下文)。沒有多少模式切換可以修復這段特定的代碼。

我開始想也許這是與,我聽說過有關。

不是。 Delphi編譯器沒有任何不可變的字符串。不可變字符串的概念只是作爲未來變化而浮現的東西。如果做出了改變,那麼首先需要在移動編譯器中完成。


這個問題其實只是一個相當簡單的錯誤,在您發佈的代碼中顯然沒有任何測試。使用Remove是錯誤的。該方法不會就地修改字符串。相反,它會返回一個刪除了字符的新字符串。該代碼應閱讀:

Result := Result.Remove(I, 1); 

的原因,誰編碼ExtractHeaderFields開發商已經犯了這個錯誤是誰設計的名爲Remove方法不正確地串助手代碼。由於Remove是一個動詞,你會期望它在原地進行操作。一個不修改主題的方法,並返回一個新的實例,就像這個方法所做的那樣,應該給它一個名詞。所以這個方法應該被命名爲Remnants。它看起來好像RTL設計人員複製了.net命名的地方也存在相同的缺陷。

您應該提交QC報告(如果尚不存在)。我知道XE4更新1剛剛發佈。它包含修復程序似乎是合理的。

你的其他選擇,因爲我看到他們,主要有:

與XE3
  1. 棒直到XE4充分調試。
  2. 在您的項目中包含Web.HTTPApp單元的副本並自行修復錯誤。
+0

你是絕對正確的大衛,就是這樣 - Delphi的Web.HTTPApp中的一個漏洞,將結果遺漏給了Result。感謝您的教程。 –

+0

提交QC報告。稍後我會檢查這是否在更新#1中得到修復。 –

+0

當忽略函數結果時,似乎沒有用於警告的編譯器選項。在這種情況下,即使是編譯器錯誤也應該引發(因爲有一個選項可以用這樣的指令標記「TStringHelper」)。 –

相關問題