2013-06-12 18 views
8

Sto cercando di eseguire il debug del comportamento che è apparso solo quando la mia app di grandi dimensioni - funzionante bene in XE3 - viene eseguita dopo la compilazione con XE4. Il problema sembra causare alcune stringhe tra virgolette (es. "MyString") per mantenere le loro quotazioni anche dopo essere state "de-quotate" da TPageProducer in Web.HTTPProd. Ad esempio, si consideri il codice qui sotto che è piccolo estratto da questa Delphi unità di fonte Web.HTTPApp:Perché TPageProducer non rimuove le virgolette dalle stringhe?

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; 

vedo questo chiamato quando uso TPageProducer e posso vedere la mia buona stringa di origine andare nella routine ExtractHeaderFields sopra e quindi nella funzione 'DoStripQuotes'. Entrando in DoStripQuotes e guardando 'Result' si dimostra che non cambia, anche quando viene chiamato Result.Remove (per togliere la citazione). Quando prendo questa routine 'DoStripQuotes' in una semplice app di test, non verrà compilata, dicendomi che 'Result.Ancora' non è consentito. Presumo quindi che Result, sebbene sia definito come 'string', deve essere un altro tipo di stringa nel contesto di Web.HTTPProd.

Quindi penso che forse questo è qualcosa a che fare con le "stringhe immutabili" di cui ho sentito parlare. Ho letto questo SO question e, anche se ho capito bene, potrei fare un consiglio più pratico.

In particolare, vorrei risposte alle seguenti domande:

  1. Che tipo di 'stringa' è 'Risultato' se è consentito l'Result.Length notazione?
  2. C'è un modo in cui posso dire al compilatore di usare la compatibilità XE3 per un'unità? (Questo potrebbe permettermi di vedere dove il problema sta originando). Ho risposto {$ ZEROBASEDSTRINGS ON}/OFF ma questo sembra causare ancora più caos e non so cosa sto facendo!

Grazie per qualsiasi aiuto.

LATER EDIT: come indicato nella risposta accettata di seguito, si tratta di un bug nell'unità VCL Web.HTTPApp.pas che dovrebbe contenere "Result: = Result.Remove (I, 1)" in due punti attorno alla riga 2645 e non "Result.Remove (I, 1)"

risposta

9

Che tipo di 'stringa' è 'Risultato' se la notazione Result.Length è consentita?

E 'solo la stessa vecchia string, alias di UnicodeString, che hai utilizzato dal Delphi 2009. La differenza è che questo codice utilizza il nuovo helper record (in particolare SysUtils.TStringHelper). Questo è ciò che ti permette di usare la notazione . su una variabile stringa.

C'è un modo in cui posso dire al compilatore di utilizzare la compatibilità XE3 per un'unità?

No. Il codice in questione è un'unità di libreria ed è progettato per essere compilato in una modalità particolare. Inoltre, non è possibile ricompilarlo facilmente a meno che non si compili da solo la RTL/VCL. Anche se ci fosse una tale modalità, non sarebbe di aiuto in quanto il codice è semplicemente sbagliato (vedi sotto). Nessuna quantità di cambio di modalità può risolvere questo particolare pezzo di codice.

arrivare a pensare che forse questo è qualcosa a che fare con le stringhe immutabili che ho sentito parlare.

Non lo è. Nessuno dei compilatori di Delphi ha ancora stringhe immutabili. Il concetto di stringhe immutabili è solo qualcosa che è stato fluttuato come un cambiamento futuro. E se il cambiamento è stato fatto, aspettati che venga creato prima nei compilatori mobili.


Il problema è in realtà solo un bug piuttosto semplice nel codice che hai postato che chiaramente non ha avuto alcun test. L'uso di Remove è sbagliato. Questo metodo non modifica la stringa sul posto. Invece restituisce una nuova stringa che ha rimosso il personaggio. Il codice dovrebbe leggere:

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

La ragione per cui lo sviluppatore che codificato ExtractHeaderFields ha fatto questo errore è che chi ha progettato il codice di stringa di aiutante chiamato il metodo Remove in modo non corretto. Dal Remove è un verbo che ci si aspetta che funzioni sul posto. Un metodo che non modifica l'oggetto e restituisce una nuova istanza, come questo metodo, dovrebbe avere un nome che è un nome. Quindi questo metodo dovrebbe essere chiamato qualcosa come Remnants. Mi sembra che i progettisti di RTL abbiano copiato il nome di .net in cui esiste anche lo stesso difetto.

È necessario inviare un rapporto di controllo qualità, se non ne esiste già uno. So che l'aggiornamento 1 XE4 è appena stato rilasciato. È plausibile che contenga una soluzione.

Le altre opzioni, come li vedo, sono:

  1. Stick con XE3 fino XE4 è sufficientemente debug.
  2. Includere una copia dell'unità Web.HTTPApp nel progetto e correggere personalmente gli errori.
+0

Hai assolutamente ragione David, è quello che è stato: un bug nel Web.Help di Delphi che ha lasciato il compito a Risultato. Grazie anche per il tutorial. –

+0

Rapporto QC inviato. Verificherò in seguito se questo è stato risolto nell'aggiornamento n. 1. –

+0

Sembra che non ci sia un'opzione del compilatore per un avviso quando si ignora un risultato di una funzione. In questo caso dovrebbe essere stato sollevato anche un errore del compilatore (dato che c'era un'opzione per contrassegnare 'TStringHelper' con tale direttiva). –

Problemi correlati