![]() |
Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Ich stehe etwas auf dem Schlauch. Folgender Code lief unter XE7, später 10.0 Seattle und, ich meine, testweise unter 10.2 Tokyo ohne Probleme:
Delphi-Quellcode:
Nun, mit 10.4, gibt es eine Access Violation beim Verlassen der Methode, wenn er die lokale Variable AnsiString finalisieren will. Das kann man auch provozieren indem man vor dem letzten
uses System.SysUtils, System.DateUtils, WinApi.ImageHlp;
class function TLinkerTimeStamp.GetTimeUTC(const FileName: string): TDateTime; var LI: TLoadedImage; asAnsi: AnsiString; begin // Nach: http://stackoverflow.com/a/8438985/2298252 asAnsi := AnsiString(FileName); //TEncoding.Default.GetBytes(FileName); Win32Check(MapAndLoad(PAnsiChar(asAnsi), nil, @LI, False, True)); try Result := LI.FileHeader.FileHeader.TimeDateStamp / SecsPerDay + UnixDateDelta; finally UnMapAndLoad(@LI); end; end;
Delphi-Quellcode:
noch hinzufügt:
end;
Delphi-Quellcode:
. Die AV findet statt in
Finalize(asAnsi);
Delphi-Quellcode:
durch ein (für mich mystisches) Kommando
System._LStrClr(..)
Code:
.
LOCK DEC [EDX-skew].StrRec.refCnt { threadsafe dec refCount }
Was geschieht hier, und warum geschieht es? |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
PS: Es gibt keine Probleme wenn ich an MapAndLoad nicht mehr die
Delphi-Quellcode:
, sondern stattdessen eine zusätzlich eingeführte
PAnsiChar(asAnsi)
Delphi-Quellcode:
-Variable die auf
PAnsiChar
Delphi-Quellcode:
zeigt, übergebe. Übergebe ich
@asAnsi[1]
Delphi-Quellcode:
direkt statt eine zusätzliche lokale Variable einzuführen bleibt es beim Crash.
@asAnsi[1]
Heißt: Folgendes läuft ganz harmlos durch, wie früher:
Delphi-Quellcode:
class function TLinkerTimeStamp.GetTimeUTC(const FileName: string): TDateTime;
var LI: TLoadedImage; asAnsi: AnsiString; asPAnsiChar: PAnsiChar; begin // Nach: http://stackoverflow.com/a/8438985/2298252 asAnsi := AnsiString(FileName); asPAnsiChar := Addr(asAnsi[1]); Win32Check(MapAndLoad(asPAnsiChar, nil, @LI, False, True)); try Result := LI.FileHeader.FileHeader.TimeDateStamp / SecsPerDay + UnixDateDelta; finally UnMapAndLoad(@LI); end; end; Kann das jemand erklären? |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Wie ist MapAndLoad definiert?
Ich würde auch im Debugger mal Speicherauszüge anschauen vor und nach dem Aufruf. Nicht das die Aufrufende Methode mist baut und es nur jetzt auffällt. |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
![]()
Code:
Wie es in der WinApi.ImageHlp.pas aussieht, hab ich jetzt noch nicht nachgeschaut.
BOOL IMAGEAPI MapAndLoad(
PCSTR ImageName, PCSTR DllPath, PLOADED_IMAGE LoadedImage, BOOL DotDll, BOOL ReadOnly ); Hab hier nur ein 10.3.3 installiert, aber da ist es schon ein PWideChar.
Delphi-Quellcode:
In XE ist es noch PAnsiChar, was auch richtig ist, denn PCSTR ist ein C++-char, also 1 Byte groß,
type
MarshaledAString = _AnsiChar; LPSTR = MarshaledAString; function MapAndLoad(ImageName, DllPath: LPSTR; LoadedImage: PLoadedImage; DotDll, ReadOnly: Bool): Bool; stdcall; und diese Funktion gibt es nur in der einen ANSI-Variante. Fazit: Jemand hat diese Typdefinition geschrottet. |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Nicht richtig gelesen... Es heißt MarshaledAString
MarshaledAString = _PAnsiChr |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Ups, in der Zeile verrutscht und falsch gecopytundpastet. :oops:
Gut, dann stimmt es in 10.3.3 noch. In 10.4 kann ich grad nicht nachsehn, aber wenn es dort auch noch stimmt, dann dreht wohl der Compiler durch. Müsste man mal sehn wie es im Assembler zwischen den Delphiversionen aussieht, was dort generiert wird. |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Zitat:
Delphi-Quellcode:
Bzw. wird bei
function _LStrToPChar(const S: _AnsiStr): _PAnsiChr;
begin if Pointer(s) = nil then Result := @(PEmptyString(@EmptyStringA[1])^.Nul) else Result := Pointer(s); end;
Delphi-Quellcode:
immer noch _LStrToPChar aufgerufen?
PAnsiChar(asAnsi)
|
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Hallo,
ohne mich durch die Details gearbeitet zu haben: Hr. Eißing hat im Webinar zu 10.4 erwähnt, dass sich die default-Einstellung von $ZEROBASEDSTRINGS in 10.4 geändert hat. Vielleicht hat es etwas damit zu tun? Schöne Grüße, Meik |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Ich glaube das betrifft nur die iOS und Android-Compiler, oder?
Es muss ja irgend etwas mit der Referenzzählung des Strings sein, denn durch Einführen einer zusätzlichen Variable funktioniert es ja wieder. |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Zitat:
Bei dem Aufruf
Delphi-Quellcode:
wird implizit _LStrToPChar aufgerufen. Wenn Du über die zusätzlichen Variable mit
MapAndLoad(PAnsiChar(asAnsi)...
Delphi-Quellcode:
gehst, dann wird _LStrToPChar nicht benutzt.
asPAnsiChar := Addr(asAnsi[1]);
Ich vermute, wenn Du statt
Delphi-Quellcode:
wieder
asPAnsiChar := Addr(asAnsi[1]);
Delphi-Quellcode:
benutzen würdest, kracht es wieder. Denn dann wird wieder _LStrToPChar aufgerufen. Das würde dann zeigen, dass es nicht an der zusätzlichen Variablen liegt, sondern am Aufruf von _LStrToPChar.
asPAnsiChar := PAnsiChar(asAnsi);
|
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Ah danke, jetzt habe sogar ich das verstanden. Und ja, unter 10.4 Sydney sieht es nun anders aus:
Delphi-Quellcode:
Vorher (laut dir):
function _LStrToPChar(const S: _AnsiStr): _PAnsiChr;
begin if Pointer(s) = nil then Result := @(PEmptyString(Pointer(EmptyStringA))^.Nul) else Result := Pointer(s); end;
Delphi-Quellcode:
Aus
function _LStrToPChar(const S: _AnsiStr): _PAnsiChr;
begin if Pointer(s) = nil then Result := @(PEmptyString(@EmptyStringA[1])^.Nul) else Result := Pointer(s); end;
Delphi-Quellcode:
wurde
@EmptyStringA[1]
Delphi-Quellcode:
. Vielen Dank. Ich konnte nichts finden weshalb das geändert worden ist. Außerdem spielen leere Strings hier ja keine Rolle. Wahrscheinlich hat sich noch mehr geändert.
Pointer(EmptyStringA)
PS: Unter 64 Bit funktioniert alles weiterhin wie gehabt. Wahrscheinlich steckt irgendwo ein Fehler in diesem mystischen Assemblercode. PPS: Ich habe mal einen neuen Eintrag angelegt unter ![]() |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Ich kann das leider nicht reproduzieren. Ich habe es einmal mit
Delphi-Quellcode:
versucht. Hättest du einmal ein komplettes Beispiel mit dem Aufruf? Das würde ich bei einer Bugmeldung dringend empfehlen: Genau schreiben wie es reproduzierbar ist, wenn irgendwie möglich. Ansonsten wird dein Jira-Eintrag vermutlich als nicht reproduzierbar geschlossen...
GetTimeUTC(Application.ExeName)
|
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Ja, du hast Recht. Das Merkwürdige:
Delphi-Quellcode:
liefert bei mir auch keinen Fehler. Nehme ich aber stattdessen
var dateTime := GetTimeUTC( ParamStr(0) )
Delphi-Quellcode:
kommt es zur AV. Allerspätestens hier endet mein Verständnis. Jetzt müssen die Profis ran.
var timestamp := DateTimeToStr( GetTimeUTC( ParamStr(0) ) );
Ich habe dem Report eine komplette .DPR angehangen ( ![]() |
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Zitat:
Delphi-Quellcode:
und
@EmptyStringA[1]
Delphi-Quellcode:
erzeugt - solange die Strings nicht Zerobased sind - ja exakt den gleichen Assemblercode. Damit ist diese Fehlermöglichkeit raus.
Pointer(EmptyStringA)
|
AW: Code mit AnsiString lief unter 10.0 Seattle, crasht unter 10.4 Sydney
Die Ursache war übrigens eine ganz andere: Die Definition von
Delphi-Quellcode:
ist in 10.4 falsch, was dann dazu führte dass in den Bereich vom AnsiString reingeschrieben wurde.
TLoadedImage
( ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz