2013-06-12 20 views
8

私は、XE3でうまく動作する大規模なアプリケーションがXE4でコンパイルされた後に実行された場合にのみ表示される動作をデバッグしようとしています。この問題は、Web.HTTPProdのTPageProducerによって「de-quoted」された後でも、引用符付きの文字列(「MyString」など)が引用符を保持するように見えます。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ルーチンに入る見ることができたとき、私はと呼ばれるこれを見ると、たとえば、その下に小さなこのデルファイソースユニットWeb.HTTPAppから抽出されたコードを考えます'DoStripQuotes'関数に入力します。 DoStripQuotesに移動して「結果」を見ると、Result.Removeが呼び出されても(引用符を削除するために)変更されないことが示されます。この「DoStripQuotes」ルーチンを単純なテストアプリケーションに取り込むと、コンパイルされず、「Result.anything」が許可されていないことがわかります。私はその結果を仮定しますが、 'string'はWeb.HTTPProdのコンテキスト内の別のタイプの文字列でなければなりません。

これは私が聞いたことのある「不変な文字列」と関連するかもしれないと思うかもしれません。私はこのことを約SO questionと読んでいますが、私は要点を得ていますが、もっと実用的なアドバイスをすることができました。

具体的には、私は次の質問に対する答えをしたいと思います:

  1. 表記Result.Lengthが許可されている場合は、「結果は」「文字列」のタイプは何?
  2. ユニットに「XE3」互換性を使用するようにコンパイラに指示する方法はありますか? (これにより、問題が発生している場所を知ることができます)。私は$ {ZEROBASEDSTRINGS ON}/OFFをやったことがありますが、これはもっと混乱の原因と思われ、私は何をしているのか分かりません!

ありがとうございました。

次の受諾された回答に記載されているように、これはVCLユニットWeb.HTTPApp.pasのバグで、2645行目の2か所で "Result:= Result.Remove(I、1)

答えて

9

Result.Lengthという表記が許可されている場合、どのようなタイプの 'string'が 'Result'ですか?いいえ、「Result.Remove(I、1)

それは、stringちょうど同じ古いですあなたはDelphi 2009以来使用してきたことを、UnicodeStringにエイリアス。違いは、このコードでは新しいレコードヘルパー(具体的にはSysUtils.TStringHelper)を使用していることです。これは文字列変数に.の表記法を使用できるようにするものです。

ユニットに「XE3」互換性を使用するようにコンパイラに指示する方法はありますか?

いいえ問題のコードはライブラリ単位であり、特定のモードでコンパイルされるように設計されています。さらに、自分でRTL/VCLをコンパイルしない限り、簡単に再コンパイルすることはできません。このようなモードがあったとしても、コードが間違っているので、それは役に立たないでしょう(下記参照)。この特定のコードを修正することはできません。

私は多分これは私が聞いた不変の文字列とは何かである思考に着きます。

そうではありません。いずれのDelphiコンパイラも不変の文字列を持っていません。不変の文字列の概念は、将来の変化として浮かび上がったものです。変更が行われた場合は、モバイルコンパイラで最初に作成されることを期待してください。


問題は、あなたが投稿したコードではまったくテストされていませんでした。 Removeの使用は間違っています。このメソッドは、インプレースの文字列を変更しません。代わりに、文字が削除された新しい文字列を返します。コードは次のようになります。

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

ExtractHeaderFieldsをコード化された開発者は、このミスを犯したことの理由は、誰が間違ってRemove方法をという名前の文字列ヘルパーのコードを設計していることです。 Removeは動詞であるため、インプレースで動作することが期待されます。このメソッドのように、サブジェクトを変更せずに新しいインスタンスを返すメソッドには、名詞である名前を付ける必要があります。したがって、このメソッドの名前はRemnantsのようにする必要があります。 RTL設計者が同じ欠陥が存在する.netネーミングをコピーしたように見えます。

QCレポートがない場合は、提出する必要があります。私は、XE4アップデート1がリリースされたことを知っています。修正が含まれていることは間違いありません。私はそれらを見るように

あなたの他のオプションは、以下のとおりです。XE4までXE3と

  1. スティックが十分にデバッグされています。
  2. Web.HTTPAppユニットのコピーをプロジェクトに含めて、バグを自分で修正してください。
+0

あなたはまさにデビッドです。それはデルファイのWebのバグです.HTTPAppはResultへの割り当てを取りやめました。チュートリアルもありがとう。 –

+0

品質報告書が提出されました。更新#1でこれが修正されたかどうかを後で確認します。 –

+0

関数の結果を無視すると、警告のコンパイラオプションがないようです。この場合、コンパイラエラーが発生しているはずです(このようなディレクティブで 'TStringHelper'をマークするオプションがあれば)。 –

関連する問題