ClearMemory(*MemoryBuffer, length)
Hi Leute,
kann sich den auch nach einem AllocateMemory() noch was in dem Speicherbereich finden?
Noch ne Frage:
Wenn man Netzwerkfunktionen verwendet, brauch man ja zwangsläufig einen Empfangsbuffer, nur wie leert man den am Besten oder muss man den vielleicht gar nicht leeren?
Gruß
Scarabol
kann sich den auch nach einem AllocateMemory() noch was in dem Speicherbereich finden?
Noch ne Frage:
Wenn man Netzwerkfunktionen verwendet, brauch man ja zwangsläufig einen Empfangsbuffer, nur wie leert man den am Besten oder muss man den vielleicht gar nicht leeren?
Gruß
Scarabol
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea
PB-V: 4
WinXP
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea
PB-V: 4
WinXP
- 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
'AllocateMemory()' füllt den allokierten Speicher automatisch mit Nullen. Man
kann aber mittels 'globalalloc_()' auch einen nicht nullgesetzten
Speicherbereich allokieren und darin evtl. noch Informationen von anderen
Programmen finden. Und ich denke, darum geht es hier gerade. Dass man
den Speicher auf Null setzt, bevor man wieder 'FreeMemory()' aufruft.
Kann mich aber auch irren.
kann aber mittels 'globalalloc_()' auch einen nicht nullgesetzten
Speicherbereich allokieren und darin evtl. noch Informationen von anderen
Programmen finden. Und ich denke, darum geht es hier gerade. Dass man
den Speicher auf Null setzt, bevor man wieder 'FreeMemory()' aufruft.
Kann mich aber auch irren.
> oder muss man den vielleicht gar nicht leeren
Es ist nicht notwendig, den Speicher zu leeren. Dazu muss man wissen, dass PureBasic das Ende von Strings im Speicher mit einer 0 markiert (Chr(0)).
Experiment:
Allokiere 10 Bytes, Poke 9 Zeichen hinein. PokeS() von PureBasic hängt automatisch eine 0 an, die 10 allokierte Bytes werden also vollständig ausgenutzt. Dann Poke 5 Zeichen. Das Poken von 5 Zeichen bewirkt, dass 6 Zeichen geschrieben werden (weil...? Ja genau! PB's null!)
Das sieht so aus:
Soll also nun ein gepoketer Text gelesen werden, geschieht das mit PeekS(). Der Knackpunkt: Es werden nur alle Daten bis zum ersten auftretenden 0-Byte gelesen!
Zur Erinnerung: In unserem *buffer befinden sich 2 nullen. Eine an Stelle 10 von dem ersten PokeS. Die zweite null befindet sich ja an Stelle 6.
PeekS() liest also korrekt nur bis zur Stelle 6, und das, obwohl noch "Müll" von einem älteren PokeS im Speicher steckt.
Diesen Müll kann man nachweisen, indem man zur Speicheradresse den Offset von 6 dazu addiert. Das bewirkt, dass PeekS() erst an der 7. Stelle anfängt zu lesen und zwar wie gehabt bis zum nächsten Null-Byte. In diesem Fall allerdings wäre das nächste Null-Byte an 10. Stelle, denn es stammt ja noch vom 1. Poke-Versuch.
Fazit: Auch bei Netzwerkbuffern benötigt man kein ClearMemory. Denn ReceiveNetworkData() tut nichts anderes, als Poken. Es benutzt (vermute ich) auch PokeS() intern, was ein automatisches Anhängen eines 0-Bytes bewirkt. Liest du dann die Daten später noch mit PeekS(), läuft alles korrekt ab (siehe oben).
Und selbst wenn es Probleme gibt: ReceiveNetworkData() gibt die Anzahl an empfangenen Bytes zurück, diese Angabe kann man im Bedarfsfall auch noch benutzen.
Fazit: Auch beim normalen Poken+Peeken benötigt man nicht unbedingt ein ClearMemory.
Es ist nicht notwendig, den Speicher zu leeren. Dazu muss man wissen, dass PureBasic das Ende von Strings im Speicher mit einer 0 markiert (Chr(0)).
Experiment:
Allokiere 10 Bytes, Poke 9 Zeichen hinein. PokeS() von PureBasic hängt automatisch eine 0 an, die 10 allokierte Bytes werden also vollständig ausgenutzt. Dann Poke 5 Zeichen. Das Poken von 5 Zeichen bewirkt, dass 6 Zeichen geschrieben werden (weil...? Ja genau! PB's null!)
Das sieht so aus:
Code: Alles auswählen
*buffer=AllocateMemory(10)
PokeS(*buffer, "ZYXWVUTSR")
PokeS(*bufer, "abcef")
Debug PeekS(*buffer)
Debug PeekS(*buffer+6)
Zur Erinnerung: In unserem *buffer befinden sich 2 nullen. Eine an Stelle 10 von dem ersten PokeS. Die zweite null befindet sich ja an Stelle 6.
PeekS() liest also korrekt nur bis zur Stelle 6, und das, obwohl noch "Müll" von einem älteren PokeS im Speicher steckt.
Diesen Müll kann man nachweisen, indem man zur Speicheradresse den Offset von 6 dazu addiert. Das bewirkt, dass PeekS() erst an der 7. Stelle anfängt zu lesen und zwar wie gehabt bis zum nächsten Null-Byte. In diesem Fall allerdings wäre das nächste Null-Byte an 10. Stelle, denn es stammt ja noch vom 1. Poke-Versuch.
Fazit: Auch bei Netzwerkbuffern benötigt man kein ClearMemory. Denn ReceiveNetworkData() tut nichts anderes, als Poken. Es benutzt (vermute ich) auch PokeS() intern, was ein automatisches Anhängen eines 0-Bytes bewirkt. Liest du dann die Daten später noch mit PeekS(), läuft alles korrekt ab (siehe oben).
Und selbst wenn es Probleme gibt: ReceiveNetworkData() gibt die Anzahl an empfangenen Bytes zurück, diese Angabe kann man im Bedarfsfall auch noch benutzen.
Fazit: Auch beim normalen Poken+Peeken benötigt man nicht unbedingt ein ClearMemory.
PB 4.30
Code: Alles auswählen
Macro Happy
;-)
EndMacro
Happy End
Ähem... also ich will jetzt nicht behaupten, daß ich alles zu 100% weiß, aber ich weiß wenigstens zu 100%, daß das, was Du da gerade geschrieben hast, völliger Quatsch istDenn ReceiveNetworkData() tut nichts anderes, als Poken. Es benutzt (vermute ich) auch PokeS() intern, was ein automatisches Anhängen eines 0-Bytes bewirkt.

Wie würdest Du sonst jemals eine 0 übers Netzwerk schicken können? Das läuft anders, es werden sog. Netzwerk-Pakete empfangen, die ihrerseits im Header eine Information darüber besitzen, wie lang das ist. D.h. es wird erstmal diese Längenangabe ausgelesen, und danach wird einfach genau so viel aus dem Speicher gelesen, wie dort drinsteht. Auch wenn zwischendrin mal eine 0 vorkommt, das ist in dem Fall egal, Du kannst übers Netzwerk jedes beliebige Byte schicken, die Daten werden einfach immer entsprechend in einen sog. Data Frame verpackt (bzw. in mehrere, aber das ist wieder ein anderes Thema und auch nicht so wichtig, wichtig ist nur daß da nicht mit Null-Bytes gearbeitet wird. Das wird nur bei Strings so gemacht weil dort die 0 nicht benötigt wird bzw. eben genau als solches "Trennzeichen" definiert wurde (siehe ASCII-Tabelle)).


ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
- 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
PureBasic nutzt ja auch nur deswegen die Nullterminierung, weil Windows es
nicht anders macht. Turbo Pascal und alle Nachfolger bis Delphi 2007 kennen
zwar auch nullterminierte String, machen es aber üblicherweise so, dass vor
dem String steht wie lange er ist. Dadurch kann man auch Nullbytes in den
String schreiben. Aber zur Kommunikation mit der Win-API muss auch Delphi
mit nullterminierten Strings arbeiten.
nicht anders macht. Turbo Pascal und alle Nachfolger bis Delphi 2007 kennen
zwar auch nullterminierte String, machen es aber üblicherweise so, dass vor
dem String steht wie lange er ist. Dadurch kann man auch Nullbytes in den
String schreiben. Aber zur Kommunikation mit der Win-API muss auch Delphi
mit nullterminierten Strings arbeiten.
Das ist wahr. Das habe ich mich beim Posten auch gefragt, dann aber vergessen, darauf einzugehen.ZeHa hat geschrieben:Ähem... also ich will jetzt nicht behaupten, daß ich alles zu 100% weiß, aber ich weiß wenigstens zu 100%, daß das, was Du da gerade geschrieben hast, völliger Quatsch istDenn ReceiveNetworkData() tut nichts anderes, als Poken. Es benutzt (vermute ich) auch PokeS() intern, was ein automatisches Anhängen eines 0-Bytes bewirkt.
Wie würdest Du sonst jemals eine 0 übers Netzwerk schicken können?
Deshalb habe ich ja auch geschrieben, dass man im Notfall immernoch die Längenangabe in Bytes zur Hilfe nehmen kann, die ReceiveNetworkData() zurückgibt.
PB 4.30
Code: Alles auswählen
Macro Happy
;-)
EndMacro
Happy End
Ich würd mal sagen, das liegt nicht an Windows, sondern eher an Cweil Windows es nicht anders macht.



ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Wieso muss Assembler etwas schneller sein?LCD hat geschrieben:Habe ein Benchmark durchgeführt, und es gibt so gut wie keinen Unterschied zu der WinAPI Funktion ZeroMemory_(*Memory,Length), was mich etwas irritiert. Normalerweise müsste Assembler etwas schneller sein.
Im Grunde sind die Win-API auch nur Assemblercode.
Der Vorteil ist halt das man mit dem Code nicht auf die API angewiesen ist.
Das ist der Assemblercode der RtlZeroMemory Funktion von Windows XP:
Code: Alles auswählen
7C91311B PUSH EDI
7C91311C MOV EDI,DWORD PTR SS:[ESP+8]
7C913120 MOV ECX,DWORD PTR SS:[ESP+C]
7C913124 XOR EAX,EAX
7C913126 CLD
7C913127 MOV EDX,ECX
7C913129 AND EDX,3
7C91312C SHR ECX,2
7C91312F REP STOS DWORD PTR ES:[EDI]
7C913131 OR ECX,EDX
7C913133 JNZ SHORT ntdll.7C913139
7C913135 POP EDI
7C913136 RETN 8
7C913139 REP STOS BYTE PTR ES:[EDI]
7C91313B POP EDI
7C91313C RETN 8
Code: Alles auswählen
7C91312F REP STOS DWORD PTR ES:[EDI]
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
