string: = const: warum unterschiedliche Implementierung für local und result?

8

In der Delphi-Funktion wird das Ergebnis häufig als Var-Parameter implementiert (trotz QC-Ticket kein Out-Parameter).

String-Konstanten sind grundsätzlich Variablen mit negativem Refcounter, die die automatische Speicherzuordnung unterdrücken sollen. Ссылка

Es unterdrückt es wirklich: Der folgende Code leckt nicht.

%Vor%

Aber ändere die manipulierte Variable - und es beginnt sofort stark zu lecken.

%Vor%

Es stellt sich heraus, dass string := const abhängig von LValue mit verschiedenen Aufrufen implementiert wird:

  1. Ergebnis: AnsiString - & gt; LStrAsg
  2. Ergebnis: UnicodeString: - & gt; UStrAsg
  3. Lokale Variable: UnicodeString: - & gt; UStrLAsg
  4. Lokale Variable: AnsiString: - & gt; LStrLAsg

Und während die letzten beiden den Zeiger wie erwartet klonen, kopieren die ersten beiden die Zeichenfolge in eine neue Instanz, so als würde ich ihnen UniqueString call hinzufügen.

Warum dieser Unterschied?

    
Arioch 'The 11.10.2012, 10:08
quelle

2 Antworten

1

Nach der Diskussion mit David Heffernan beginne ich zu denken, dass der Delphi-Compiler einfach nicht weiß, welchen Wert er der Variablen zuweist. Art von "Art Löschung", die Platz hat. Es kann keine globale Konstante von der lokalen On-Stack-Variablen und dem lokalen String-Ausdruck unterscheiden. Es kann nicht feststellen, ob die Quelle nach dem Beenden der Funktion existieren würde. während wir wissen, dass String-Literal oder globale Konstante oder irgendetwas mit Lebensdauer unabhängig von der Ausführung der Funktion ist - der Compiler verliert nur diese Informationen. Und stattdessen spielt es defensiv und klont immer den Wert - nur für die Chance, dass es aufhören würde zu existieren. Ich bin mir nicht sicher, aber das sieht vernünftig aus. Obwohl die Folgen dieser rohen, wahllosen Codegenregel in Delphi noch ein Gotcha sind: - (

    
Arioch 'The 11.10.2012, 11:21
quelle
9

Konstante Zeichenfolgen werden in Delphi immer kopiert, wenn sie einer anderen globalen -Variablen, aber nicht einer lokalen -Variablen zugewiesen werden, um Zugriffsverletzungen in Grenzfällen zu vermeiden.

Benutze die Quelle, Luke!

Sehen Sie sich diese Code-Extraktion von System.pas an:

%Vor%

Kurz gesagt, um Designfehler zu vermeiden und Zugriffsverletzungen zu vermeiden, wenn eine DLL oder ein Paket entladen wird und einige konstante Werte enthält, die an den Hauptprozess zurückgesendet werden, wird immer eine lokale Kopie erstellt.

Sie haben zwei Funktionen:

  • LStrAsg oder UStrAsg , das vom Compiler generiert wird, wenn eine Zeichenfolge die Chance hat, eine Konstante zu sein - das ist der obige Code;
  • LStrLAsg oder UStrLAsg (hinzugefügt L steht für "local"), das vom Compiler generiert wird, wenn die Quellzeichenfolge lokal ist, also keine Konstante sein muss: In diesem Fall wird P.refCnt < 0 nicht überprüft , so wird es schneller als der obere Code sein.
Arnaud Bouchez 11.10.2012 11:56
quelle