AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Compiler ersetzt Variable durch Konstante - AV zur Laufzeit
Thema durchsuchen
Ansicht
Themen-Optionen

Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

Ein Thema von Der schöne Günther · begonnen am 12. Nov 2013 · letzter Beitrag vom 12. Nov 2013
Antwort Antwort
Der schöne Günther

Registriert seit: 6. Mär 2013
6.159 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 13:52
Eine WinAPI-Methode erwartet einen PWideChar den sie eventuell auch verändern wird. Meine Methode hat dafür eine lokale Variable des Typs. Sieht so aus:

Delphi-Quellcode:
const
   defaultStrValue: String = 'Das ist ein String';
var
   myString: String;
   myWideChar: PWideChar;
begin

   myString := defaultStrValue;
   myWideChar := PWideChar(myString);
   
   WinApiAufruf(myWideChar); // AV
end;
Die Zugriffsverletzung führe ich eindeutig auf einen Schreibversuch auf die Konstante zurück. Der Compiler sieht wohl "He, die Variable ist ja genau das gleiche wie die Konstante" und wird nicht die Variable myString sondern die Konstante defaultStrValue casten.
Jetzt das kuriose: Ändere ich die myWideChar-Zuweisung mit diesen drei Zeichen ab, läuft alles wunderbar:

myWideChar := PWideChar(myString+''); Völlig klar: Das Anhängen eines leeren Strings erzeugt einen neuen String der dann nach PWideChar gecastet wird. Und diese Adresse ist schreibbar.



Meine Frage: Ist das hier ein Compilerfehler oder Übereifrige Optimierung? Oder hätte ich glasklar damit rechnen müssen?
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 14:11
Das ist as-designed. Es wird nur eine Referenz benutzt. Du kannst das aber so machen (ungetestet):
Delphi-Quellcode:
const
   defaultStrValue: String = 'Das ist ein String';
var
   myString: String;
   myWideChar: PWideChar;
begin

   myString := defaultStrValue;
   UniqueString(myString);
   myWideChar := PWideChar(myString);
   
   WinApiAufruf(myWideChar); // AV
end;
So musst du das auch bei CreateProcess machen, sonst knallt es bei Unicode, wenn du z.B. einen const Parameter an CreateProcess übergibst.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.159 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 14:27
Ganz genau der Fall (CreateProcess) war es auch

Ist mir bislang nie aufgefallen da ich die Variable, ausgehend von der Konstante, immer noch einmal verändert hatte.

Fazit: Copy on Write für Delphi-Strings. Bei der Zuweisung variablerString := konstanterString hat man natürlich auch erst einmal nur die Adresse der Konstante dort. Muss man aber auch erstmal drauf kommen
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#4

AW: Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 14:31
Genau dieser Fall ist aber doch beschrieben (unterstes Beispiel):
Zitat:
Aufrufe von CreateProcessW

Die Unicode-Version (CreateProcessW) der Windows-API-Funktion CreateProcess verhält sich etwas anders als die ANSI-Version. Folgendes (sinngemäß übersetzt) findet sich in Bezug auf den lpCommandLine-Parameter in MSDN:

"Die Unicode-Version dieser Funktion, CreateProcessW, kann den Inhalt dieses Strings ändern. Daher darf dieser Parameter kein Zeiger auf schreibgeschützten Speicher sein (wie eine const-Variable oder ein literaler String). Wenn dieser Parameter ein Konstanten-String ist, könnte die Funktion eine Zugriffsverletzung verursachen."

Wegen dieses Problems könnte vorhandener Code, der CreateProcess aufruf, eine Zugriffsverletzung verursachen.

Im Folgenden finden Sie einige Beispiele für solchen problematischen Code:
Delphi-Quellcode:
// Übergabe einer String-Konstanten
CreateProcess(nil, 'foo.exe', nil, nil, False, 0,
  nil, nil, StartupInfo, ProcessInfo);
// Übergabe eines Konstantenausdrucks
  const
    cMyExe = 'foo.exe'
  CreateProcess(nil, cMyExe, nil, nil, False, 0,
    nil, nil, StartupInfo, ProcessInfo);
// Übergabe eines Strings mit dem Referenzzähler -1:
const
  cMyExe = 'foo.exe'
var
  sMyExe: string;
  sMyExe := cMyExe;
  CreateProcess(nil, PChar(sMyExe), nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo);
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.159 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 14:35
Ja, bei MSDN steht das natürlich auch. Das habe ich schon verstanden, ich hatte nur instinktiv damit gerechnet, dass spätestens beim Cast nach PWideChar eine neue Kopie vom String angelegt und diese gecastet würde.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#6

AW: Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 14:43
Naja,
Zitat:
// Übergabe eines Strings mit dem Referenzzähler -1:
dürfte aber nicht im MSDN stehen
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#7

AW: Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 14:49
Ja, bei MSDN steht das natürlich auch. Das habe ich schon verstanden, ich hatte nur instinktiv damit gerechnet, dass spätestens beim Cast nach PWideChar eine neue Kopie vom String angelegt und diese gecastet würde.
Ein simples Beispiel zeigt, daß ein Cast auf PChar eben nur ein Cast ist. Der Delphi-String ist vom Speicher-Layout schon kompatibel zum PChar, so daß der Cast eigentlich nur den Compiler zufrieden stellen soll (nicht nur, ich weiß).

Folgendes Beispiel verdeutlicht das:

Delphi-Quellcode:
  myString := defaultStrValue;
  myString[1] := 'W';
funktioniert.


Delphi-Quellcode:
  myString := defaultStrValue;
  //UniqueString(myString);
  PChar(myString)^ := 'W';
funktioniert nicht ohne das UniqueString.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.159 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 15:10
UniqueString ! Großartig, das ist doch um einiges eleganter als einen leeren String irgendwo anzuhängen oder sich selber was zu basteln.

Danke dafür
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#9

AW: Compiler ersetzt Variable durch Konstante - AV zur Laufzeit

  Alt 12. Nov 2013, 15:21
Bei dynamischen Arrays gibt es garkein Copy on Write.

Dort wäre eine Art Äquivalent zum UniqueString das Copy.

Delphi-Quellcode:
var
  A, B: array ob Integer;

SetLength(A, 1);
A[0] := 123;
A := Copy(B); // A := B;
B := A;
B[0] := 456;
ShowMessage(IntToStr(A[0]); // 123 und ohne Copy ist es auch 456
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:26 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz