AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Frage zum Aufbau eines Strings

Ein Thema von SebE · begonnen am 16. Jan 2005 · letzter Beitrag vom 16. Jan 2005
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#11

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 14:34
ohne zu wissen ob das was mirage228 geschrieben hat richtig ist: Klar ist -4 außerhalb des zulässigen. 0 ist auch außerhalb des zulässigen, trotzdem kann man drauf zugreifen (es steht eben nur nicht der String drin). Wenn das von mirage228 stimmt, dann wird einfach genügend speicher reserviert für den String und der Index[1] greift prinzipiell eben erst auf die Xte-Stelle des reservierten Speichers zu und nicht wirklich auf die 1te oder 0te

@Muetze: ist klar das es nur bei den AnsiStrings so ist, ansonsten ist ja wie beim PChar alles an einer Stelle und nicht überall im speicher verteilt mit extra speicherverwaltung (die ist eben wegen den referenzzeugs nur bei den Ansistrings dabei)
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#12

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 14:39
Ich würd' mir gern mal die Length-Funktion anschauen, um näheres zu erfahren, aber ich finde sie nicht in der System.pas
Sebastian
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: München
11.412 Beiträge
 
Delphi 11 Alexandria
 
#13

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 14:39
Wurde ja alles schon erwähnt, deswegen nur noch mal kurz zusammenfassend.

Der String ist ein Pointer auf einen Speicherbereich. Selbst also nichts anderes als ein Pointer. Dieser Pointer zeigt auf das erste Zeichen des Strings, welches mit StringVar[1] anzusteuern geht. Vor diesem Zeichen gibt es acht weitere Bytes, deren Struktur wie folgend ist (Copyright Borland, System.pas):
Delphi-Quellcode:
type
  PStrRec = ^StrRec;
  StrRec = packed record
    refCnt: Longint;
    length: Longint;
  end;
Das heisst, die Bytes -8 bis -5 sind der Referenzzähler (wie oft wird dieser String genutzt) und die Bytes -4 bis -1 sind die Länge des Strings.

Zu Pascalzeiten war es anders, die Strings dort waren so aufgebaut, wie es heute die ShortStrings sind. Diese hatten eine maximale Länge von 255 Zeichen. Das 0. Byte (also StringVar[0]) speicherte die Länge des Strings (0-255) und die folgenden Bytes den Inhalt.

Die Strings in den heute gängigen Pascal-Versionen können bis zu 2 GB (nicht 4 GB!) groß werden. Da dieser Wert zum Speichern eindeutig mehr als 1 Byte benötigt, kann dieser Wert (StringVar[0]) für normale Strings auch nicht mehr angesteuert werden (Compiler-Fehlermeldung).

......
Daniel W.
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Benutzerbild von mirage228
mirage228

Registriert seit: 23. Mär 2003
Ort: Münster
3.750 Beiträge
 
Delphi 2010 Professional
 
#14

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 14:40
Zitat von SebE:
Ich würd' mir gern mal die Length-Funktion anschauen, um näheres zu erfahren, aber ich finde sie nicht in der System.pas
Hi,

siehe den Hinweis in der System.pas:

Zitat:
unit System; { Predefined constants, types, procedures, }
{ and functions (such as True, Integer, or }
{ Writeln) do not have actual declarations.}
{ Instead they are built into the compiler }
{ and are treated as if they were declared }
{ at the beginning of the System unit.
}
Die Prozedur ist also wahrscheinlich in den Compiler eingebaut.
Edit: Siehe zusätzlich Post von sakura unter mir

mfG
mirage228
David F.

May the source be with you, stranger.
PHP Inspection Unit (Delphi-Unit zum Analysieren von PHP Code)
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: München
11.412 Beiträge
 
Delphi 11 Alexandria
 
#15

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 14:41
Zitat von SebE:
Ich würd' mir gern mal die Length-Funktion anschauen, um näheres zu erfahren, aber ich finde sie nicht in der System.pas
Diese unterliegt auch der "Copmiler-Magic" und hat verschiedene Implementationen mit unterschiedlichen Namen. Die gängigste ist folgende (Copyright © Borland; System.pas):
Delphi-Quellcode:
function _LStrLen(const s: AnsiString): Longint;
{$IFDEF PUREPASCAL}
begin
  Result := 0;
  if Pointer(s) <> nil then
    Result := PStrRec(Integer(s) - sizeof(StrRec)).length;
end;
{$ELSE}
asm
        { ->    EAX str }

        TEST EAX,EAX
        JE @@done
        MOV EAX,[EAX-skew].StrRec.length;
@@done:
end;
{$ENDIF}
......
Daniel W.
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: München
11.412 Beiträge
 
Delphi 11 Alexandria
 
#16

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 14:43
Zitat von SirThornberry:
0 ist auch außerhalb des zulässigen, trotzdem kann man drauf zugreifen
Falsch, der Compiler gibt Dir bei Strings eine Fehlermeldung

......
Daniel W.
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#17

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 14:43
Oh weiß gar nicht wie ich auf die 4 GB gekommen bin. Hmm, jetzt wo du mich wieder mal dran erinnert hast das ein String ja nur ein Pointer war (sizeof(String) war ja schon immer 4 (war mir entfallen *schäm*)) ist mir das ganze mit dem speicher auch wieder bissl klarer (und vor allem das mit dem -4, -8).

@Sakura: Der Compiler schon, aber wenn man über den umweg der Pointer drauf zugreift kommt keine AV (so hatt ichs eigentli auch versucht)
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.481 Beiträge
 
Delphi 10.1 Berlin Professional
 
#18

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 16:16
Zitat von Muetze1:
@SirThornberry: Die Einschränkung mit String und DLL gilt nur für AnsiString, da diese mit internen Referenzen arbeiten - im Gegensatz dazu hat man mit WideStrings oder ShortStrings keine Probleme (keine Referenzen).
Diese Erklärung ist falsch. Es liegt nicht am Referenzzähler, sondern daran, dass man bei AnsiStrings "nicht mitbekommt", wenn man Speicher reserviert oder freigibt. Da Delphi einen eigenen Speichermanager mitbringt, der von Windows größere Speicherblöcke anfordert und diese dann in kleineren Blöcken an die Anwendung gibt, braucht der Delphi-Speichermanager eine Liste mit den Blöcken. Hat man nun eine zusätzliche DLL, enthält diese eine eigene Kopie des Delphi-Speichermanagers die ihre eigene Block-Liste besitzt.
Übergibt man nun einen AnsiString an eine DLL und diese verändert diesen, passiert es, dass der AnsiString an den DLL-Speichermanager zum Freigeben übergeben wird, der mit dem Speicherbereich aber gar nichts anfangen kann, weil der AnsiString ja im EXE-Speichermanager reserviert wurde. In diesem Moment kracht es dann.
Bei WideStrings läuft das ganze anders ab. Da WideString hauptsächlich wegen COM eingeführt wurden und auch nicht-Delphi-Anwendungen COM-Server und Clients sein können, war Borland gezwungen, den von Microsoft vorgegebenen WideString-Speichermanager zu benutzen. Deswegen wird bei WideString nicht AllocMem/FreeMem sondern Windows.SysAllocStringLen/SysFreeString aufgerufen.
Bei ShortStrings liegt die Sache ganz anders. ShortStrings werden nicht dynamisch reserviert, sondern werden einfach im Datensegment oder auf dem Stack erzeugt. Beim Stack wird ein "SUB ESP,256" für einen lokale Variable "s: ShortString" durchgeführt. Und dieser Speicher muss auch nicht realloziert werden, weil die 255 Zeichen Maximum sind, weswegen der EXE und DLL-Speichermanager sich nicht in die Quere kommen.
Also alles was mit AllocMem/GetMem/FreeMem arbeitet (dazu gehören AnsiString, dyn. Array, Klassen, New, Dispose, ...) können nur ohne Probleme an eine DLL übergeben werden, wenn diese nur ohne Reallozierung (ReallocMem) oder Freigeben und neu Reservieren zugreift. Bei AnsiStrings ist es aber sehr wahrscheinlich, dass man den String Realloziert ohne das man das direkt im Code geschrieben hat. Wenn man also die Compiler-Magic für AnsiStrings nicht auswendig kennt, sollte man bei AnsiString sehr vorsichtig sein.

Und nun warum das ganze kein Problem bei Packages ist, die ja auch "nur" DLLs sind. Bei Packages hat Borland das DLL-Format dahingehend erweitert, als dass der Compiler alle öffentlichen Funktionen, Methoden und einige spezielle, nur für den Compiler/RTL wichtige Funktionen exportiert. In diesen Compiler-Magic-Funktionen stecken dann so informationen wie welche Unit im Package enthalten sind, ... Diese Informationen erlauben es der RTL nun zu verhindern, dass die BPL einen eigenen Speichermanager bekommt. Somit benutzen die EXE und die BPL ein und denselben Speichermanager, und können somit AllocMem und FreeMem in beiden Modulen ungehindert aufrufen, weil beide auf dieselble Block-List zugreifen.
Die BorlandMM.dll macht nun nichts anderes, als dass sie in der EXE und in der DLL mittels der Unit ShareMem, die per SetMemoryManager den Speichermanager der EXE und der DLL auf die BorlandMM.dll setzt, den gleichen Speichermanager für beide Module anbietet und somit AllocMem und FreeMem in beiden Modulen aufgerufen werden können.
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.481 Beiträge
 
Delphi 10.1 Berlin Professional
 
#19

Re: Frage zum Aufbau eines Strings

  Alt 16. Jan 2005, 16:21
Zitat von SirThornberry:
@Sakura: Der Compiler schon, aber wenn man über den umweg der Pointer drauf zugreift kommt keine AV (so hatt ichs eigentli auch versucht)
Das liegt daran, dass der Compiler bei S[Index] automatisch eine 1 von Index abzieht. Müsste ungefähr so aussehen
Code:
MOV ESI, S
MOV EDX, [Index]
MOV AL, [ESI+EDX-1]
Wenn mal also immer von 0 ab zählt und dann mit S[Index+1] zugreift, optimiert der Compiler das zu (ungefähr):
Code:
MOV ESI, S
MOV EDX, [Index]
MOV AL, [ESI+EDX]
Also wird die -1 entfernt, was ein ganz kleinen, fast unmessbaren Geschwindigkeitszuwachs bringt. Macht aber die Lesbarkeit ein wenig kaputt.

Wenn man nun die String S in einen Zeiger konvertiert, entfällt das -1 ganz von alleine, weil es sich ja nicht mehr um einen String handelt.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


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 09:44 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