![]() |
Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Hallo.
Ich hätte nochmal eine Frage bzgl. Strings in Record-Stukturen und den Unterschieden zwischen Delphi7 und BDS 2009/2010 (bezogen auf Unicode). Nehmen wir mal folgende Struktur an, die so unter Delphi7 implementiert ist:
Delphi-Quellcode:
Nehmen wir weiter an, eine Record-Instanz wird wie folgt erzeugt:
type
TMyStructure = record LastName: string[32]; FirstName: string[32]; end; PMyStructure = ^TMyStructure;
Delphi-Quellcode:
Das Ganze unter Delphi7 kompiliert und funzt. Jetzt portieren wir das mal auf BDS 2009 und machen folgendes:
var
MyStructure: PMyStructure; begin New(MyStructure); MyStructure^.LastName := 'Mustermann'; MyStructure^.FirstName := 'Max'; ... end;
Delphi-Quellcode:
Wie machen aus den ShortStrings/AnsiStrings nun UnicodeStrings. Was passiert nun bei "New(MyStructure)" und
type
TMyStructure = record LastName: string; FirstName: string; end; PMyStructure = ^TMyStructure; beim Zuweisen der Record-Variablen, wenn diese statt mit einer Konstante mit einem übergebenen String (z.B. innerhalb einer Methode) gefüllt werden? Interessant finde ich, das ich dieses Konstrukt zwischen einer DLL und einer Host-Applikation einsetze, und ich beliebig lange Unicode-Strings übergeben kann (SimpleShareMem/FastMM4)....hin und zurück. Dabei müsste doch nun der Speichermanager von Delphi zunächst die Länge des Strings ermitteln und entsprechen Platz reservieren, oder? Wie gesagt, eigentlich funktioniert das zwischen diversen Host-Applikationen und jeder Menger DLL's (PlugIns). Jetzt habe ich aber an drei Stellen einer ziemlich großen Anwendung ein für mich nicht erklärbares Phänomen, bei dem z. B. übergebene Strings an eine Methode plötzlich weg sind oder in einer anderen seltsamer Speichercode steht. Ich werde also das Gefühl nicht los, das hier manchmal was nicht sooo richtig funktioniert und überlege, ob das mit diesen Record-Strukturen zusammenhängt. Wenn ich jetzt wieder die ShortStrings einführe [], dann muss ich halt an tausenden Codestellen einen Typcast machen (String-> AnsiString)....und daher die Frage, ob es hieran überhaupt liegen kann....!?! Vielen Dank & Gruß, kaju |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Da hat sich überhaupt nichts geändert.
Delphi-Quellcode:
String[x] ist undbleibt ein
type
TMyStructure = record LastName: string[32]; FirstName: string[32]; end; PMyStructure = ^TMyStructure;
Delphi-Quellcode:
mit begrenzter Länge,
ShortString
also ein "Record" aus einem LängenByte, direkt gefolgt von X AnsiChars und ein ShortString ist nunmal nur "ANSI". ( String[255] = ShortString )
Delphi-Quellcode:
Hier ist String ein LongString,
type
TMyStructure = record LastName: string; FirstName: string; end; PMyStructure = ^TMyStructure; also ein Pointer auf die String-Daten Der Einzige unterschied ist, das <= D2007: String = AnsiString >= D2009: String = UnicodeString Aber dieses ändert nichts an der Speicherverwaltung. [add] ![]() |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Diese beiden Deklarationen sind auch unabhängig von der Delphi-Version verschieden. ShortStrings sind auch bei >= D2009 AnsiStrings
|
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Hallo.
Das string[xx] unter Delphi auch ein Shortstring mit max. 255 Zeichen ist, ist mir klar. Nur ist die Frage, wie der Speicher von Delphi allociert wird: Gebe ich die max. Länge in Klammern an, weiß der Compiler ja, wieviel Zeichen zu reservieren sind. Nutze ich stattdessen einen String (ohne Klammern!) und weiße ihm einen in einer Methode als Parameter übergebenen String zu, weiß der Compiler die Länge ja nicht, da es erst zur Laufzeit passiert. Wird nun der Speicher dynamisch erweitert? Macht dass der Memory-Manager alleine? Kann ich mich ohne Zutun darauf verlassen, oder könnte da evtl. andere Speicher überschrieben werden? Gruß, kaju |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Das wurde doch erklärt?
Ein String[x] und ShortString (aka String[255]) entspricht dieser Struktur:
Delphi-Quellcode:
Ein String/AnsiString/WideString/UnicodeString ist ein Zeiger auf seine Daten,
type
MyShortString = packed record Len: Byte; // entspricht Data[0] Data: array[1..x] of AnsiChar; end; also im Record steht dort nur der Pointer (mit seinen aktuell 4 Byte) und der Rest (der Stringinhalt) liegt irgendwo anders. Und der Speicher, auf welchen der Pointer zeigt, wird von Delphi (der CompilerMagic) automatisch verwaltet. Das ist in allen Delphiversionen gleich. (natürlich solange sie den entsprechenden String-Typen kennen) |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Hallo.
Okay..sorry...das ich hatte ich so nicht verstanden - nu' isses klar 8-) Ich hätt's eigentlich wissen müssen...also liegt hier nicht mein Problem...mysteriös. Oder fällt Euch nochwas ein, warum ein an eine Methode übergebener String dort nicht ankommt? Danke & lieben Gruß, kaju |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Also nochmal um das klarzustellen: Du darfst an diesem Rekord NICHTS verändern. Es muss auch in D2009 so aussehen:
Delphi-Quellcode:
Das einzige was irgendwie zu Problemen führen könnte ist, dass man halt beachten muss, dass LastName und FirstName jetzt AnsiStrings sind und keine UnicodeStrings wie "String".
type
TMyStructure = record LastName: string[32]; FirstName: string[32]; end; PMyStructure = ^TMyStructure; |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Wieso....????
Ich habe bereits alle Strukturen umgestellt, und rein durch "String" ersetzt...wieso ist das jetzt doch ein Problem? Wenn doch statt z.B. vorher bei String[32] eben 32 Bytes reserviert wurden und jetzt bei "String" nur 4 Bytes für den Pointer (oder so), und über "CompilerMagic" der benötigte Platz für den String reserviert ist, müsste doch alles okay sein, oder etwas doch nicht..??!?!? Lieben Gruß, kaju |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Nachtrag:
Das war ja eben der Grund, warum ich alle Strukturen von AnsiString auf String/Unicode umgestellt habe. Ich hätte tausende Stellen Typecasten müssen, weil der Compiler da natürlich gemeckert hat, das evtl. Inhalt verlorengeht, wenn man einen String in AnsiString umwandeln möchte. Da die Stringlänge jetzt aber beliebig lang sein kann, war damit auch das Problem beseitigt...hoffe ich zumindest, da ich halt jetzt komischer Speicherüberlappungen habe. Umgestellt wurde von Delphi7/WindowsXP auf BDS 2009/Windows7 + Updates aller Komponenten. Jetzt muss ich halt nach für nach ausschließen, woher das Problem kommt. Gruß, kaju |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Zitat:
|
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Zeig mal Code an denen die Probleme auftauchen.
Und speicherst du diese Records in eine Datei und liest sie wieder aus? Dann wette ich, dass deine Speicher- und Ladefunktionen falsch sind (zeig die mal bitte) |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Dumme Frage am Rande:
Bei den Shortstrings ist S[0] die Länge, S[1] der erste Buchstabe usw. Bei den AnsiStrings, wo ist da die Länge? Nach meinem Verständnis verbirgt sich hinter S dann ungefähr so etwas:
Delphi-Quellcode:
Gruß
record
S_Adr : pointer; S_Lang: integer; end; K-H |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Stimmt: +1 Byte für die Längenangabe.
Codestelle ist schwierig...da das ein Konstrukt aus Host läd PlugIn, Plugin sammelt Daten, PlugIn ruft Callback auf, Host nimmt Daten entgegen und reicht diese an eine interne Methode weiter, und hier gibt's das Problem. Überliefert wird ein Zeiger auf eine Rekordsstruktur, die ich wunderbar vom Host aus typecasten und auslesen kann. Wenn ich aus dieser Struktur aber einen String an eine interne Methode übergebe, sehe ich beim debuggen, das dieser zwar noch an die Methode übergeben wird, dort aber nicht ankommt. Ich suche aber mal das Codestück raus....kommt gleich... Gruß, kaju |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Zitat:
Delphi-Quellcode:
Würde ich mal sagen. Wenn ich falsch liege, dann steinigt mich :mrgreen:
ShortString = packed record
Len: Byte; // In er Praxis so nicht schreibbar aber ihr wisst was ich meine :mrgreen: Data: Array[1..Len] of Char; end; LongStringData = packed record Len: Cardinal; Data: Array of Char; end; AnsiString = ^LongStringData; // eigentlich ja eher sowas.. AnsiString = ^LongStringData.Data; // Aber egal.. :D |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Du versuchst also diese Records über EXE/DLL-Grenzen hinweg zu übertragen?
A) sollte man bei sowas nie String, Integer und immer mit packed Records arbeiten, da unterschiedliche Compiler/Optionen sonst den Record verändern und andere Typen verwenden würden. B) Hast du auch einen SharedMemoryManager eingerichtet? Strings werden im Delphi-SpeicherManager abgelegt und da hat standardmäßig jede EXE/DLL ihre eigene Instanz eines SpeicherManagers. [add] *den Neutral General steinige*
Delphi-Quellcode:
@S zeigt auf Len, bzw. den Recordanfang
ShortString = packed record
Len: Byte; Data: Array[1..Len] of AmsiChar; end;
Delphi-Quellcode:
@S zeigt auf den Pointer
type
// Delphi 2007 und kleiner PStrRec = ^StrRec; StrRec = packed record refCnt: Longint; // Referenzzähler length: Longint; // Stringlänge data: array[1..x] of AnsiChar; end; // Delphi 2009+ PStrRec = ^StrRec; StrRec = packed record codePage: Word; elemSize: Word; refCnt: Longint; length: Longint; data: array[1..x] of AnsiChar; // für AnsiString oder WideChar für UnicodeString end; @S[1] und Pointer(S), bzw PChar(S) zeigen auf "data", bzw. das erste Zeichen und nicht auf den RecordAnfang also String/AnsiString/UnicodeStrin entsprechen intern jeweil ihrer PStrRec-Variante ( WideString ist was Anderes und der Entspricht einem OLE-String, verwaltet von der OleAuth.dll ) |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Zitat:
Und ansonsten... Ok ok :mrgreen: |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Danke für die Erläuterungen,
Auch wenn ich den "String"-records per se nicht traue, wenn ein Pointer übergeben wird dann sind das doch in der Zwischenzeit absolute Adressen und nicht mehr diese Segment-Krücken DS:xxxxx ES:yyyy, dann dürfte doch nichts mehr schief gehen? Gleiches Typverständnis voraus gesetzt.( und naturlich vorhandene Zugriffsrechte) Gruß K-H |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Diese "Segment-Krücken" gibt es in der Art nur noch im RealMode werden heute eigentlich nicht mehr verwendet. Unter Windows umfassen alle Segmente (bis auf fs) den kompletten Speicher und heben somit eine Segmentierung auf.
Wobei ich allerdings nicht weiß, was das jetzt hier mit zu tun hat? Verstehe deine Frage oder dein Problem nicht |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Wenn die Adresse (Pointer) "absolut" ist, sollte es ja für jedes Programm (Prozess) möglich sein korrekt auf an dieser Adresse liegende Daten zuzugreifen.
Und die Ausgangsfrage legt ja nahe, das dies nicht der Fall ist. Gruß K-H |
Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
Hallo,
Zitat:
Da jedes Programm (Prozesse) 2 GB Speicher (Win32) anfordern kann, ist doch klar, dass das trotzdem virtuell erfolgt. Heiko |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:08 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