Was sind die Werte am Ende eines Strings?

Für allgemeine Fragen zur Programmierung mit PureBasic.
SMaag
Beiträge: 57
Registriert: 08.05.2022 12:58

Was sind die Werte am Ende eines Strings?

Beitrag von SMaag »

der für einen String angelegte Speicher ist immer etwas Länger als der String selbst!
Das Ende ist mit 0en gefüllt, dann kommen noch 8 Byte.
Genau diese 8 Byte interessieren mich!

hier ein Code, der zeigt, dass es so ist!
Es werden 2 Strings direkt hintereinander im Speicher angelegt und dann die Inhalte per Debug ausgegeben!

Code: Alles auswählen

Define s1.s, s2.s, L

s1 = "0000"
s2 = "0000"

Debug "@s1 = " + @s1 
Debug "@s2 = " + @s2
L= Abs(@s1-@s2)
Debug "MemorySize of s1, s2 = " + L + " Bytes"
Define ptr, N

Debug #Null$
Debug "Memory of s1"
For ptr = @s1 To @s2 + L -SizeOf(Integer) Step SizeOf(Integer); Step SizeOf(Character)
  If ptr = @s2
    Debug "Memory of s2"
  EndIf
  Debug "N= " + N + "  :  ptr = " + ptr + "  :  " + PeekI(ptr)
  n+1
Next
Das ist die Debug Ausgabe

@s1 = 12387792
@s2 = 12387824
MemorySize of s1, s2 = 32 Bytes

Memory of s1
N= 0 : ptr = 12387792 : 3145776
N= 1 : ptr = 12387796 : 3145776
N= 2 : ptr = 12387800 : 0
N= 3 : ptr = 12387804 : 0
N= 4 : ptr = 12387808 : 0
N= 5 : ptr = 12387812 : 0
N= 6 : ptr = 12387816 : 1849233171 <-- um diese Werte geht es
N= 7 : ptr = 12387820 : 234916727 <-- um diese Werte geht es
Memory of s2
N= 8 : ptr = 12387824 : 3145776
N= 9 : ptr = 12387828 : 3145776
N= 10 : ptr = 12387832 : 0
N= 11 : ptr = 12387836 : 0
N= 12 : ptr = 12387840 : 0
N= 13 : ptr = 12387844 : 0
N= 14 : ptr = 12387848 : 1715013395 <-- um diese Werte geht es
N= 15 : ptr = 12387852 : 167807863 <-- um diese Werte geht es
Benutzeravatar
Bisonte
Beiträge: 2413
Registriert: 01.04.2007 20:18

Re: Was sind die Werte am Ende eines Strings?

Beitrag von Bisonte »

SMaag hat geschrieben: 20.01.2023 23:55 Es werden 2 Strings direkt hintereinander im Speicher angelegt
Wer sagt das ?

Nur weil du sie direkt nacheinander definierst, heisst das noch lange nicht, dass sie direkt hintereinander "hängen". Das ist nur gegeben, wenn du Arrays nutzt oder selber den Speicher mit Poke füllst.

Die Nullen schliessen einen String ab. Alles was danach kommt ist reiner Zufall.
PureBasic 6.00 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6941
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Was sind die Werte am Ende eines Strings?

Beitrag von STARGÅTE »

SMaag hat geschrieben: 20.01.2023 23:55 der für einen String angelegte Speicher ist immer etwas Länger als der String selbst!
Das Ende ist mit 0en gefüllt, dann kommen noch 8 Byte.
Genau diese 8 Byte interessieren mich!

hier ein Code, der zeigt, dass es so ist!
Es werden 2 Strings direkt hintereinander im Speicher angelegt und dann die Inhalte per Debug ausgegeben!
Was ist denn das für eine Argumentationskette?
Wer sagt dir, dass String immer genau hintereinander liegen müssen und der Zwischenraum nicht für was anderes benutzt wird? Außerdem, woher weißt du, dass die nullen und diese 8 Byte die du meinst nicht schon vom nächsten String sind?
Zumindest bei mir liegt nach s2 ja noch der temporäre String von "@s2 = " + @s2. Das siehst du wenn du ShowMemoryViewer() verwendest:

Code: Alles auswählen

0000[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
ꛅ쑒塐฀0000[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
껅챒塐਀@s2 = 38471152[NULL]
[NULL]
[NULL]
Üblicherweise haben Memory-Reservierung noch ein Kopf vorangestellt. Außerdem könnte immer etwas mehr Speicher reserviert werden um einerseits ein Vielfaches der Prozessor-Wort-Größe zu haben (4 oder 8 Byte) und andererseits bei kleinen Vergrößerungen nicht jedes mal einen neuen Speicher suchen zu müssen.

Edit: Nun die passende Ausgabe zu deinem Code.
Außdem sieht es in x64 anders aus:

Code: Alles auswählen

0000[NULL]
ɛ[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
ⵔ홴฀0000[NULL]
ɛ[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
⥔퉴਀@s2 = 39520416[NULL]
[NULL]
[NULL]
[NULL]
Und mit Purifier:

Code: Alles auswählen

0000[NULL]
஭[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
櫛វ뗍฀஭0000[NULL]
஭[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
拚ẜ뗍਀@s2 = 38995452[NULL]
[NULL]
[NULL]
[NULL]
[NULL]
PB 5.73 ― Win 10, 20H2 ― Ryzen 9 3900X ― Radeon RX 5600 XT ITX ― Vivaldi 5.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
SMaag
Beiträge: 57
Registriert: 08.05.2022 12:58

Re: Was sind die Werte am Ende eines Strings?

Beitrag von SMaag »

etwas erweitert! lt. Debug der StringAdressen liegen die 3 Strings s1 s2 s2 je 40 Byte auseinander!
Ich gehe deswegen davon aus, dass die Strings hintereinander liegen. Und es sind bei mir immer
8Bytes, egal, was ich rumdrehe! Hab das mit x32 getetet, bei x64 könnte das durchaus anders sein.

@s1 = 11142648 : $AA05F8
@s2 = 11142688 : $AA0620
@s3 = 11142728 : $AA0648
MemorySize of s1, s2 = 40 Bytes : 28

So wie das aussieht, sind die letzten 8 Byte Müll.

etwas rumprobiert ändert sich die Speicherlänge ja nach Stringlänge immer auf volle 8 Byte
angefangen bei 24, 32, 40, 48, 56, 64

Code: Alles auswählen

#cst_Size = SizeOf(Integer)
Define s0.s, s1.s, s2.s, s3.s, L

s0 = "0000000000"
s1 = "0000000000"
s2 = "0000000000"
s3 = "0000000000"

Debug "@s1 = " + @s1 + " : " + Hex(@s1)
Debug "@s2 = " + @s2 + " : " + Hex(@s2)
Debug "@s3 = " + @s3 + " : " + Hex(@s3)
L= Abs(@s1-@s2)

Debug "MemorySize of s1, s2 = " + L + " Bytes : " + Hex(L, #PB_Word) 
Define ptr, N

Debug #Null$
Debug "Memory of s1"
For ptr = @s1 To (@s1 +L - #cst_Size) Step #cst_Size; Step SizeOf(Character)
  Debug "N= " + N + "  :  ptr = " + ptr + "  :  " + Hex(PeekI(ptr), #PB_Long)
  n+1
Next

N=0
Debug "Memory of s2"
For ptr = @s2 To (@s2 +L - #cst_Size) Step #cst_Size; Step SizeOf(Character)
  Debug "N= " + N + "  :  ptr = " + ptr + "  :  " + Hex(PeekI(ptr), #PB_Long)
  N+1
Next

N=0
Debug "Memory of s3"
For ptr = @s3 To (@s3 +L -#cst_Size) Step #cst_Size; Step SizeOf(Character)
  Debug "N= " + N + "  :  ptr = " + ptr + "  :  " + Hex(PeekI(ptr), #PB_Long)
  N+1
Next
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6941
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Was sind die Werte am Ende eines Strings?

Beitrag von STARGÅTE »

SMaag hat geschrieben: 21.01.2023 00:40 So wie das aussieht, sind die letzten 8 Byte Müll.
<Sarkasmus> Ich denke auch :freak: </Sarkasmus>
Bitte mal diesen Blog-Beitrag lesen: Debugging tips – Part 1: Heap corruption
When Windows allocates memory, it keeps a data structure to manage the allocated memory (usually 12bytes on 32bit Windows). This data structure is normal, writable memory which means that you will not get any access error when accidentally writing over it. It is nowhere specified where this data is kept, but it is a fact that it sometimes ends up right after your allocated memory buffer.
PB 5.73 ― Win 10, 20H2 ― Ryzen 9 3900X ― Radeon RX 5600 XT ITX ― Vivaldi 5.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
SMaag
Beiträge: 57
Registriert: 08.05.2022 12:58

Re: Was sind die Werte am Ende eines Strings?

Beitrag von SMaag »

Ok ich glaub ich hab's raus!

Die Strings werden mit einem Align 8 angelegt.
Im Speicher steht dann der String gefolgt von einer $00 (Nullterminierung) danach kommt Müll, was noch vorher im Speicher war.
Das sieht man, wenn man sich die Bytes ansieht und dann einfach mal einen um 1 Zeichen kürzeren String drüberschreibt.
Nach der Nullterminierung steht dann noch das alte Zeichen.

Was ich eigentlich rauskriegen wollte!
ob es eine Möglichkeit gibt, die Länge des reservierten Speichers eines Strings zu ermitteln.

MemorySize(@MyString) schlägt fehl!
deshalb die Idee, mal nachzusehen, was da im Speicher steht!
Benutzeravatar
mk-soft
Beiträge: 3554
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Was sind die Werte am Ende eines Strings?

Beitrag von mk-soft »

Bringt nichts, solange du nicht den Speicher komplett selber verwaltest mit allem was dazu gehört.
Macht also keinen sinn den Speicher zu analysieren, da du nicht weist was dort ausserhalb von den dir zugewiesenen Speicher enthält.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Mijikai
Beiträge: 751
Registriert: 25.09.2016 01:42

Re: Was sind die Werte am Ende eines Strings?

Beitrag von Mijikai »

Für Windows OS gib es z.B. VirtualQuery_() um an zusätzliche Informationen zu kommen.
Ob es sinnvoll ist, ist eine andere Frage.

Beispiel:

Code: Alles auswählen

EnableExplicit

Procedure.i RegionSize(*Address)
  Protected mbi.MEMORY_BASIC_INFORMATION
  Protected size.i
  While VirtualQuery_(*Address,@mbi,SizeOf(MEMORY_BASIC_INFORMATION))
    If mbi\State = #MEM_COMMIT And mbi\Protect & 254 And Not mbi\Protect & #PAGE_GUARD
      size + mbi\RegionSize
      *Address + mbi\RegionSize
    Else
      Break
    EndIf
  Wend
  ProcedureReturn size
EndProcedure  
  
Procedure.i Main()
  Protected *str.String
  Protected mbi.MEMORY_BASIC_INFORMATION
  *str = AllocateMemory(SizeOf(String))
  Debug "GROßE DER STRING STRUKTUR " + MemorySize(*str)
  InitializeStructure(*str,String)
  Debug "AM ANFANG BELEGTER SPEICHER: " + MemoryStringLength(@*str\s)
  *str\s = "Hello World!"
  Debug *str\s
  Debug "BELEGTER SPEICHER NACH KOPIEREN DES STRINGS: " + MemoryStringLength(@*str\s)
  Debug "GRÖßE DER SPEICHER REGION: " + RegionSize(@*str\s)
  *str\s = Space(20480)
  Debug "BELEGTER SPEICHER NACH KOPIEREN DES STRINGS: " + MemoryStringLength(@*str\s)
  Debug "GRÖßE DER SPEICHER REGION: " + RegionSize(@*str\s)
EndProcedure

Main()

End
Benubi
Beiträge: 157
Registriert: 22.10.2004 17:51
Wohnort: Berlin, Wedding

Re: Was sind die Werte am Ende eines Strings?

Beitrag von Benubi »

SMaag hat geschrieben: 21.01.2023 01:11 Was ich eigentlich rauskriegen wollte!
ob es eine Möglichkeit gibt, die Länge des reservierten Speichers eines Strings zu ermitteln.

MemorySize(@MyString) schlägt fehl!
deshalb die Idee, mal nachzusehen, was da im Speicher steht!
Ich glaube der Len() Befehl tut das. Ich glaube nicht, daß dieser nach der Nullterminierung sucht, sondern sein eigenes MemorySize() benutzt. Strings und "normale" Memory-Allocations haben verschiedene Heaps, so wie ich das verstehe. Daher geht kein MemorySize auf einem String.

Daher müsstest Du das rausrechnen können mit (Len(String$)+1)*2 (+ padding für 8 Byte Allignement). Es gibt auch StringByteLength() und MemoryStringLength() - aber das bringt ja hier nix. Vielleicht kann man mit WindowsAPI/LinuxAPI und den geheimen PB-Internals das erreichen. Es hiess mal _PB_MemoryStringBase oder sowas, aber irgendwann wurde das geändert, als ThreadSafe Optionen dazu gekommen sind, die internals sind aber etwas vertraulich und können sich auch ändern (und manchmal unterscheiden sie sich nach Platform).
Antworten