Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010 (https://www.delphipraxis.net/144580-strings-record-strukturen-delphi7-vs-bds-2009-2010-a.html)

kaju74 11. Dez 2009 11:19


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:
type
  TMyStructure = record
    LastName: string[32];
    FirstName: string[32];
  end;
  PMyStructure = ^TMyStructure;
Nehmen wir weiter an, eine Record-Instanz wird wie folgt erzeugt:

Delphi-Quellcode:
var
  MyStructure: PMyStructure;
begin
  New(MyStructure);
  MyStructure^.LastName := 'Mustermann';
  MyStructure^.FirstName := 'Max';
  ...
end;
Das Ganze unter Delphi7 kompiliert und funzt. Jetzt portieren wir das mal auf BDS 2009 und machen folgendes:

Delphi-Quellcode:
type
  TMyStructure = record
    LastName: string;
    FirstName: string;
  end;
  PMyStructure = ^TMyStructure;
Wie machen aus den ShortStrings/AnsiStrings nun UnicodeStrings. Was passiert nun bei "New(MyStructure)" und
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

himitsu 11. Dez 2009 11:33

Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
 
Da hat sich überhaupt nichts geändert.
Delphi-Quellcode:
type
  TMyStructure = record
    LastName: string[32];
    FirstName: string[32];
  end;
  PMyStructure = ^TMyStructure;
String[x] ist undbleibt ein
Delphi-Quellcode:
ShortString
mit begrenzter Länge,
also ein "Record" aus einem LängenByte, direkt gefolgt von X AnsiChars
und ein ShortString ist nunmal nur "ANSI".
( String[255] = ShortString )


Delphi-Quellcode:
type
  TMyStructure = record
    LastName: string;
    FirstName: string;
  end;
  PMyStructure = ^TMyStructure;
Hier ist String ein LongString,
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]
http://www.delphipraxis.net/internal...light=widechar

mkinzler 11. Dez 2009 11:33

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

kaju74 11. Dez 2009 11:53

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

himitsu 11. Dez 2009 12:12

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:
type
  MyShortString = packed record
    Len: Byte; // entspricht Data[0]
    Data: array[1..x] of AnsiChar;
  end;
Ein String/AnsiString/WideString/UnicodeString ist ein Zeiger auf seine Daten,
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)

kaju74 11. Dez 2009 12:25

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

Neutral General 11. Dez 2009 12:28

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:
type
  TMyStructure = record
    LastName: string[32];
    FirstName: string[32];
  end;
  PMyStructure = ^TMyStructure;
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".

kaju74 11. Dez 2009 12:32

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

kaju74 11. Dez 2009 12:35

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

gammatester 11. Dez 2009 12:37

Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
 
Zitat:

Zitat von kaju74
Oder fällt Euch nochwas ein, warum ein an eine Methode übergebener String dort nicht ankommt?

Da Deine Shortstrings 33 (nicht 32) Bytes belegen, wird mit ziemlicher Sicherheit die Speicherausrichtung {$a} bzw {$align} eine Rolle spielen. Sicher war man eigentlich nur, wenn man mit packed records arbeitet.

Neutral General 11. Dez 2009 12:38

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)

p80286 11. Dez 2009 12:54

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:
record
  S_Adr : pointer;
  S_Lang: integer;
end;
Gruß
K-H

kaju74 11. Dez 2009 12:56

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

Neutral General 11. Dez 2009 12:56

Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
 
Zitat:

Zitat von p80286
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?

An der gleichen Stelle

Delphi-Quellcode:
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
Würde ich mal sagen. Wenn ich falsch liege, dann steinigt mich :mrgreen:

himitsu 11. Dez 2009 13:08

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:
ShortString = packed record
  Len: Byte;
  Data: Array[1..Len] of AmsiChar;
end;
@S zeigt auf Len, bzw. den Recordanfang

Delphi-Quellcode:
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 zeigt auf den Pointer
@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 )

Neutral General 11. Dez 2009 13:15

Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
 
Zitat:

Zitat von himitsu
[add]
*den Neutral General steinige*

Delphi-Quellcode:
ShortString = packed record
  Len: Byte;
  Data: Array[1..Len] of AmsiChar;
end;
@S zeigt auf Len, bzw. den Recordanfang

Das hatte ich ja oben noch korrigiert ;)

Und ansonsten... Ok ok :mrgreen:

p80286 11. Dez 2009 13:33

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

Neutral General 11. Dez 2009 13:43

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

p80286 11. Dez 2009 16:53

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

hoika 11. Dez 2009 21:13

Re: Strings in Record-Strukturen: Delphi7 vs. BDS 2009/2010
 
Hallo,

Zitat:

Wenn die Adresse (Pointer) "absolut" ist
Absolute im Sinne des erzeugenden Prozesses.

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 17:10 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