PokeS ohne AllocateMemory?

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

PokeS ohne AllocateMemory?

Beitrag von 4Planes »

Hallo!

Ich dachte, ich hätte eine clevere Methode gefunden, um meinen Code einfacher und gleichzeitig flexibler zu machen, indem ich Pointer und Poke-Befehle verwende. Das hat auch so lange funktioniert, wie ich nur mit Zahlen gearbeitet habe. Bei der Verwendung von Strings bin ich auf zwei Probleme gestoßen.

Hier ist ein Beispiel-Code:

Code: Alles auswählen

Structure Settings
  ZOffset.b
  Name.s
  Speed.i
EndStructure
Global Settings.Settings

; Ohne diese Zeile gehts nicht:
Settings\Name="irgendwas"
;==============================

PokeB(@Settings\ZOffset, 7)
PokeS(@Settings\Name, "Test")
PokeI(@Settings\Speed, 999)

OpenConsole("Zeiger")
PrintN(Settings\Name)
PrintN(Str(Settings\ZOffset))
PrintN(Str(Settings\Speed))
Input()
Problem Nr. 1:
@Settings\Name ist anfangs immer 0. @Settings\Name bekommt nur eine richtige Adresse im Speicher, wenn ich vorher etwas wie Settings\Name="irgendwas" ausführe. Das gilt aber komischwerweise nur für Strings. Settings\Speed ist zwar 0, aber @Settings\Speed nicht.

Problem Nr. 2:
Wenn ich hier PokeS(@Settings\Name, "Test") statt "Test" einen längeren Namen eingebe als oben bei Settings\Name="irgendwas" stürzt das Programm ab oder verhält sich seltsam. Ich nehme an, dass das daran liegt, dass Speicher überschrieben wird, der nicht überschrieben werden sollte.

Bei allen Beispielen, die ich hier im Forum gefunden habe, wird PokeS() immer in Verbindung mit AllocateMemory() verwendet. Mir ist aber nicht klar, wie man das in diesem Fall umsetzen kann.

Für Tipps, wie man den Code zum Laufen kriegen kann, wäre ich dankbar. Falls das überhaupt kein sinnvoller Ansatz ist, mit Variablen umzugehen, wäre ich auch für den Hinweis dankbar.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: PokeS ohne AllocateMemory?

Beitrag von NicTheQuick »

Das Feld "Name" ist nur ein Pointer auf den eigentlichen Inhalt des Strings. Liest du von oder schreibst du in das Feld mit den normalen PB-Befehlen wird automatisch festgestellt, ob ein zu schreibender String noch an die selbe Speicherstelle passt oder nicht. Falls nicht, wird neuer Speicher alloziert, der String dort hin geschrieben, der alte Speicher freigegeben und der Pointer an die neue Stelle umgebogen.
PokeS macht das alles nicht. Das arbeitet low-level, das heißt es geht immer davon aus, dass an der Stelle genug Speicher zur Verfügung steht und schreibt einfach los. Falls dort nicht genug ist, gibt es entweder schon beim Schreiben einen Fehler oder es taucht erst einer im späteren Programmverlauf auf.

Was hast du eigentlich genau vor? Wieso willst du alles mit Poke und Peek machen? Es gibt ein paar Tricks mit Strings, die dir vielleicht weiterhelfen könnten.
Benutzeravatar
HeX0R
Beiträge: 3042
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: PokeS ohne AllocateMemory?

Beitrag von HeX0R »

Das liegt am internen Stringhandling von PB, das lässt sich nicht so einfach aushebeln.
Das einfachste wäre, wenn Du dem String eine Länge mitgibst, also so in etwa:

Code: Alles auswählen

Structure Settings
  ZOffset.b
  Name.s{32}
  Speed.i
EndStructure
Dann würde alles wieder wie gewünscht funktionieren, Du bist aber leider dann in der Länge beschränkt.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: PokeS ohne AllocateMemory?

Beitrag von ccode_new »

Hallo 4Planes,

alles was du hier mit:
PokeS(@Settings\Name, "Test")
machen willst, macht dieser Aufruf:
Settings\Name = "Test"
doch automatisch für dich, oder ?

Wozu das PokeS() ?
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

Re: PokeS ohne AllocateMemory?

Beitrag von 4Planes »

HeX0R hat geschrieben:Das liegt am internen Stringhandling von PB, das lässt sich nicht so einfach aushebeln.
Das einfachste wäre, wenn Du dem String eine Länge mitgibst, also so in etwa:

Code: Alles auswählen

Structure Settings
  ZOffset.b
  Name.s{32}
  Speed.i
EndStructure
Dann würde alles wieder wie gewünscht funktionieren, Du bist aber leider dann in der Länge beschränkt.
Vielen Dank! Das hilft doch weiter. :allright: Ich begrenze einfach den String Name in der Länge − 32 sollte sogar reichen − und dann passt das.
NicTheQuick hat geschrieben: Was hast du eigentlich genau vor? Wieso willst du alles mit Poke und Peek machen? Es gibt ein paar Tricks mit Strings, die dir vielleicht weiterhelfen könnten.
ccode_new hat geschrieben:Wozu das PokeS() ?
Peek / Poke ist mir eigentlich nicht wichtig. Mir gehts darum, mit Pointern auf Variablen zu verweisen und diesen Pointer an Prozeduren weitergeben zu können. Aber irgendwann muss man dann halt den Wert der Variable ändern und da kommt dann Poke ins Spiel. In meinem Code-Beispiel tauchte nur Poke auf, weil das der einzige Punkt ist, der mir Probleme macht.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: PokeS ohne AllocateMemory?

Beitrag von NicTheQuick »

Aber du übergibst doch normalerweise nicht einzelne Felder per Pointer, sondern eher die ganze strukturierte Variable.
Hier ein Beispiel für Strings, das dir vielleicht trotzdem hilft.

Code: Alles auswählen

EnableExplicit

Define name.String

Procedure changeName(*name.String)
	*name\s = "Dieser String ist extra etwas länger um zu zeigen, dass es klappt"
EndProcedure


name\s = "4Planes"

Debug name\s

changeName(@name)

Debug name\s
Oder angelehnt an dein Beispiel von eben

Code: Alles auswählen

EnableExplicit

Structure Settings
	ZOffset.b
	Name.s
	Speed.i
EndStructure
Define Settings.Settings

Procedure changeSettings(*setting.Settings)
	*setting\Name = "Dieser String ist extra etwas länger um zu zeigen, dass es klappt"
EndProcedure

changeSettings(Settings)


Debug Settings\Name
Debug Settings\ZOffset
Debug Settings\Speed
Antworten