 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 09.01.2013, 09:09 Titel: String im Ram |
|
|
Hi,
ich spiele gerade etwas mit Pointern, Peek, Poke etc herum. Steig da langsam durch, jedoch kann ich die Speicherung eines Strings nicht nachvollziehen. Hier mal ein Test von mir:
Code: | Dim a As String Ptr
Dim b As String
Dim c As Byte
a = allocate (Len(String))
*(a) = "hallo"
Print *(a)
?Peek (a)
?Peek (a+1)
?Peek (a+2)
?Peek (a+3)
Print ""
b = "hallo"
Print b
?Peek (@b)
?Peek (@b+1)
?Peek (@b+2)
?Peek (@b+3)
Print ""
c = 100
Print c
?Peek(@c)
sleep |
^^Das gibt mir:
Zitat: |
hallo
56
0
104
0
hallo
176
32
185
88
100
100 |
aus, nur das Byte ist richtig. Alle anderen Variablen funktionieren auch. Nur halt Strings nicht, weiß nicht wie ich dort direkt vom Speicher an ein Byte komme, das Ascii repräsentiert.
Möchte mir sowas für besonders zeitkritische Sachen aneignen um ggf Stringfunktionen zu sparen.
Mit ptr[stelle] funktioniert es, ich weiß.. aber dennoch geht auch darum, dass ich von normalen Strings oder anhand der Speicherstelle an das Char komme.
Danke. |
|
Nach oben |
|
 |
Quisslich
Anmeldungsdatum: 09.09.2012 Beiträge: 38
|
Verfasst am: 09.01.2013, 11:18 Titel: |
|
|
verstehe nicht so ganz den Sinn hinter deinen Aktionen. Auf die einzelnen Buchstaben eines Strings kannst du auf ganz einfach mit wort[index] zugreifen. Wozu also Pointer?
Code: |
Dim wort As String
wort = "hallo"
Print wort
Print Chr(wort[0])
Print Chr(wort[1])
Print Chr(wort[2])
Print Chr(wort[3])
Print Chr(wort[4])
GetKey
|
FreeBasic bietet doch schon alle möglichen Stringfunktionen. Warum da noch mal so in meinen Augen umständlich dran rumfummeln?
[EDIT]
Was deine PEEK-Versuche mit Strings angeht, so wird so wohl nicht funktionieren. Du kannst PEEK aber auch den Datentyp mitgeben.
Code: |
wort = "hallo"
Dim wortptr As String Ptr
wortptr = @wort
Print Peek(String, wortptr)
GetKey |
Das liefert dir dann aber den kompletten String zurück. Auf die einzelnen Zeichen kannst du aber wie gesagt per Index zugreifen. |
|
Nach oben |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 09.01.2013, 11:33 Titel: |
|
|
Zum einen zum besseren Verständnis sämtlicher Grundlagen, ich mache gern viel selbst bzw will dahinter schauen und zum anderen wie ich meinte, Speed. mid(), asc(), chr(), usw usw verbrauchen kompiliert sämtliche Ticks... Wenn ich jedoch ein String(-teil) direkt in seinem Speicher als Byte ändern kann, dürfte das extrem schnell sein.
Mit Konstanten gehts ja auch:
Code: |
Const p = "hallo"
?chr(Peek(@p))
?Chr(Peek(@p+1))
?Chr(Peek(@p+2))
?Chr(Peek(@p+3))
?Chr(Peek(@p+4)) |
gibt mir aus:
Nur als Beispiel, wenn ich jetzt ne Art Hashfunktion hätte, könnte ich den String direkt mit der Konstanten im Speicher verrechnen indem ich Logikoperationen wie lshift, xor und Gebimmel drauf anwende.
Zuletzt bearbeitet von storky am 09.01.2013, 11:41, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
Quisslich
Anmeldungsdatum: 09.09.2012 Beiträge: 38
|
Verfasst am: 09.01.2013, 11:39 Titel: |
|
|
Gut, das ist ein Grund
Trotzdem würde ich dir empfehlen, auf PEEK und POKE zu verzichten, da FreeBasic eigene Pointer-Funktionen bietet, die meiner Meinung nach einfacher zu handhaben sind. In der HTML-Hilfe findest du dazu auch recht anschauliche Beispiele. |
|
Nach oben |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 09.01.2013, 11:54 Titel: |
|
|
Das stimmt danke Werd ich dann bestimmt auch machen wenn ich kapiert hab was da genau passiert, hab schon mit Ollydbg rumgespielt da steht ein String auch hintereinander byteweiße am beginnenden Offset.
Gestern hat ThePuppetMaster in einem anderen Thread gemeint:
Zitat: | n String is n 12Byte (3x 4 byte uint) type |
Und ehrlich gesagt weiß ich damit nix anzufangen.
Edit:
Mal nebenbei, weiß nicht ob ich hier an der richtigen Addresse bin und auf Leute treffe die Freebasic mitentwickeln. Ich wollte mal gesagt haben, dass ich begeistert bin die Möglichkeit zu haben, mit einer einfachen Basicsprache so hardwarenahe und Plattform unabhängige Programmierung zu bewerkstelligen. Hab schon mit OpenGL und Irrlicht Wrappern was gemacht, einfach nur Spitze. Davor hab ich 8 Jahre lang VB6 gequält und war ständig für jeden einfachen Befehl auf externe Libarys angewießen, was ja auf Performance und Kompatibilität geht. (Alleine ne Variable deklarieren ->vbfreevar() in der runtime DLL )
So Schluss mit OT. |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 956 Wohnort: Austria
|
Verfasst am: 09.01.2013, 14:49 Titel: |
|
|
Du musst bedenken, dass ein String in FreeBasic nicht etwa wie in C direkt ein Pointer auf die (Nullterminierten) String-Daten darstellt, sondern eine Eigene Datenstruktur verwendet, die erst wiederrum auf die eigentlichen String-Daten verweist.
Anstatt @b musst du StrPtr(b) verwenden, um an die Adresse der eigentlichen String Daten zu kommen. Ansonsten bekommst du die Adresse des String Descriptors, der erst auf die eigentlichen String-Daten verweist und wie folgt definiert ist (C): Code: | typedef struct _FBSTRING {
char *data; // pointer auf die eigentlichen String-Daten
int len; // Länge des Strings
int size; // Allokierter Speicher
} FBSTRING; |
Obige Struktur des String Descriptors hab ich schnell er-Google-t, muss also nicht 100%ig stimmen/aktuell sein - wenn du sicher sein willst schaust du einfach im Quellcode der rtlib (Runtime Bibliothek; C) von FreeBasic nach.
Das ganze gilt übrigens nur für Strings variabler Länge. Wenn du irgendwo einen konstanten String hast, kannst du - wie du schon bemerkt hast - sehr wohl @"Hallo" u.ä. direkt verwenden. _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken) |
|
Nach oben |
|
 |
ThePuppetMaster

Anmeldungsdatum: 18.02.2007 Beiträge: 1839 Wohnort: [JN58JR]
|
Verfasst am: 09.01.2013, 15:23 Titel: |
|
|
Der FB.String ist, wie St_W schon schreiben, eine eine eigene Typen-Struktur.
Definiert in rtlib/fb_string.h wie folgt:
Code: | typedef struct _FBSTRING {
char *data; /**< pointer to the real string data */
int len; /**< String length. */
int size; /**< Size of allocated memory block. */
} FBSTRING;
|
in FB würde dies folgendermassen aussehen:
Code: |
Type _FBString
data as UByte Ptr
len as Integer
size as Integer
End Type
|
beim Erzeugen einen Strings per Dim
Code: |
Dim MyString as String
|
wird diese Datenstruktur per CAllocate angelegt.
Vergleichbar mit
Code: |
Dim MyString as String Ptr = CAllocate(SizeOf(FB.String))
|
Die Einzelnen Elemente beherbergen hierbei die nötigen Speicheroperativen Daten.
Wird z.B. ein Text hinein gespeichert, macht FB intern etwas in dieser Art:
Code: |
'Dies ist nur temporär, damit wir daten in den Speicher legen können
Dim MeinText as ZString
MeinText = "Hallo"
'hier wird der String erzeugt.
Dim MyString as String Ptr = CAllocate(SizeOf(FB.String))
With *MyString
'zuerst wird die reale länge des Textes abgespeichert
.len = Len(MeinText)
anschliessend wird ein auf mod 4 teilbares maximum der realen länge als memory-grösse festgelegt
.size = SizeOf(UInteger) * ((.len \ 4) + 1)
'danach der speicher mit dieser größe erzeugt.
.data = Allocate(.size)
'zum schluss die Daten dort hinein Kopiert
If .len > 0 Then
For X as Integer = 0 to .len - 1
.data[X] = MeinText[X]
Next
End If
End With
|
Folglich beinhaltet der String-Datentyp foglende Parameter:
1. Den Pointer auf die eigentlichen im SPeicher liegenden Daten
2. Die Länge dieser Daten
3. Die Größe des Reservierten Speicher welcher die Daten Speichert.
Sollte nun dieser Speicher erweitert werden, und noch genügend Platz reserviert worden sein, dann wird das Allocate übrsprungen. Das Spart Zeit, bei gröseren Strings.
Erst, wenn die zu SPeichernde Textmenge grösser als der Reservierte Speicher wird, löscht FB den Alten DatenSpeicher und erzeugt einen neuen mit dem modul aus der länge.
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 09.01.2013, 15:37 Titel: |
|
|
Man sollte sich allerdings nicht auf die Größe der Struktur verlassen.
Irgendwann läuft Freebasic vielleicht auch auf AMD64 und dann wird die größer sein. |
|
Nach oben |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 09.01.2013, 16:44 Titel: |
|
|
Hey vielen Dank für die ausführlichen Infos, das erklärt mir Einiges Hatte auch Probleme als ich mal versucht hatte mit openprocess ein Handle fürs Notepad zu bekommen und mit WriteProcessMemory den Textinhalt zu überschrieben. Kam jedesmal nur "Mist" bei raus weil ich, wie ich jetzt verstanden habe, die Strukturdaten da rein geschrieben hab.
Das bringt mich auf eine wunderbare Idee, wen ich zb eine Datei binär öffne, ließt das Programm ja immer soviele Daten aus wie der String lang ist. Beim letzten Lesevorgang habe ich immer das Problem, dass der String zu 99% länger ist als das letze Segment aus der Datei und der Rest wird dann mit 0 gefüllt. Da mache ich immer sowas in der Art: rtrim(lesebuffer, restlänge)
Nun könnt ich doch einfach den Integer überpoken der die Len angibt? Ok ist nicht dazu gedacht und weiß nicht wie fb damit umgeht und ob die verwaisten Daten deallociert werden, aber vom Grundprinzip muss das sehr fix gehen.
Wenn ich das richtig sehe, muss die Addresse für den Anfang des Int dafür @string + 2 sein wenn der Pointer ein UByte ist?
Ps
Ich will hier nicht jedes Detail aus Spaß auseinander fummeln um rumzunerven Jedoch stehe ich gerade wieder an genau dieser Stelle.
bufferSize ist konstant 4096
Code: | Open Path For Binary Access As #1
fSize = lof(1)
fRead = 1
If (fSize) Then
If fSize - bufferSize < 0 Then
Get #1, fRead, buffer '<- Buffer zu lang
If cXor(key, buffer, fSize) Then Put #1, buffer
Close #1
Exit Sub
EndIf
Get #1, 1, buffer
If cXor(key, buffer, 0) Then Put #1, 1, buffer
fRead += bufferSize
fSize -= bufferSize
End If
Close #1 |
Zuletzt bearbeitet von storky am 09.01.2013, 16:47, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
ThePuppetMaster

Anmeldungsdatum: 18.02.2007 Beiträge: 1839 Wohnort: [JN58JR]
|
Verfasst am: 09.01.2013, 16:47 Titel: |
|
|
Code: |
Dim TFN as Integer = FreeFile
If Open("test.txt" for binary as #TFN) <> 0 Then Print "Konnte datei nicht öffnen": End -1
Dim TFileLen as ULongInt = Lof(TFN)
Dim TBuffer as String = Space(8092)
For X as ULongInt = 1 to TFileLen Step 8092
If (X + 8092) > TFileLen Then TBuffer = Space(TFileLen - X + 1)
Get #TFN, X, TBuffer
Print TBuffer
Next
Close #TFN
End 0
|
PS: Der unterschied zwischen FB.String und ZString ist auch recht gewaltig, wenn man betrachtet, das ein ZString keine Chr(0) Speichern kann. Ein String hingegen kann solche Zeichen Speichern.
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 09.01.2013, 16:52 Titel: |
|
|
Ups und ich mach Welle von wegen "Effizienz" Ich kopier mir den Code mal Thx |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 956 Wohnort: Austria
|
Verfasst am: 09.01.2013, 17:05 Titel: |
|
|
Wenn ich dich richtig verstehe willst du den String verkürzen indem du manell die Länge setzt. Mal davon abgesehen das man das nicht machen sollte (die Struktur könnt sich ja in Zukunft ändern), sollte es kein Problem darstellen. Die in der Struktur gespeicherten Daten über die Größe des allokierten Speichers sind ja ohnehin irrelevant beim deallokieren mittels free().
Auf die Länge kannst du z.B. wie folgt zugreifen: Code: | *(Cast(Integer Ptr, @b)+1) | Ein Pointer belegt auf einem 32-bit System übrigens 4 Bytes, also findest du die Länge an @string+4, wieder vorrausgesetzt string sei ein UByte Ptr.
Auf die String Daten könntest du auf eine der folgenden Arten zugreifen: Code: | ?Chr(Peek (Peek (Integer, @b) + 2))
?Chr(Peek (*Cast(Integer Ptr, @b) + 2))
?Chr(*(*Cast(UByte Ptr Ptr, @b) + 2)) |
_________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken)
Zuletzt bearbeitet von St_W am 09.01.2013, 17:27, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
ThePuppetMaster

Anmeldungsdatum: 18.02.2007 Beiträge: 1839 Wohnort: [JN58JR]
|
Verfasst am: 09.01.2013, 17:07 Titel: |
|
|
Allerdings sollte man lieber per FB.String darauf zugreifen.
Code: |
Dim T as String
Cast(FB.String, @T)->len = 10
|
das "könnte" auch kompatibel für zukünftige zugriffe sein.
Wichtig hingegen ist es enorm, das die .len nicht grösser als die .size ist!
Andernfalls greifst du auf einen bereich zu, der auserhalb des allokierten (.size) bereichs liegt.
MfG
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] |
|
Nach oben |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 11.01.2013, 16:41 Titel: |
|
|
Danke,
habs mal probiert mit *(Cast(Integer Ptr, @b)+1) die Länge vorm letzten Auslesen zu ändern, funktioniert. Wenn man die Stringlänge nach der Benutzung sofort wieder auf die alte Länge bringt, hatte ich auch keine Probleme mit der Stabilität. Jedoch muss alles sauber in einander greifen, hatte anfangs einen Fehler drin, durch diesen nicht bemerkt wurde, dass die Länge inzwischen 0 ist -> Absturz.
Nunja ging ums Lernen und ich habe jetzt den Stringtyp komplett verstanden  |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|