Entwickler-Ecke
Dateizugriff - Merkwürdiges Verhalten bei TRegistry.ReadBinaryData
Christian213 - Do 27.06.13 09:10
Titel: Merkwürdiges Verhalten bei TRegistry.ReadBinaryData
Hallo,
ich habe hier eine gefühlte Ewigkeit an einem merkwürdigen Problem im Zusammenhang mit "ReadBinaryData" rumgedoktort.
Laut Funktionsdefinition ist ReadBinaryData(const Name: string; var Buffer; BufSize: Integer): Integer;
So, also im Prinzip auf dem gewohnten Weg ein OpenKey einen Pfad öffnen, dann einfach einen vorher definierten Puffer nebst Puffergröße übergeben und als Returncode bekommen wir die Anzahl der tatsächlich gelesenen Zeichen, richtig?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| bytesRead := regist.GetDataSize(Value); if bytesRead > 0 then begin SetLength(Buffer, bytesRead); regist.ReadBinaryData(Value, Buffer, bytesRead);
(...) end; |
Leider gibt es dann einen SIGSEGV in dem Moment, wo ReadBinaryData aufgerufen wird.
Nach langem Probieren habe ich nun folgende Lösung:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| bytesRead := regist.GetDataSize(Value); if bytesRead > 0 then begin SetLength(Buffer, bytesRead); pBuffer := Pointer(Buffer); regist.ReadBinaryData(Value, pBuffer^, bytesRead); (...)
end; |
Die Frage die sich mir stellt ist: Wieso muss ich eine untypisierte Pointer-Variable definieren und diese dann de-referenziert übergeben?
Es funktioniert so zwar, ich wüsste nur gerne warum ich hier solche Verrenkungen machen muss.
Gruß,
Christian
Moderiert von
Narses: Topic aus Sonstiges (Delphi) verschoben am Do 27.06.2013 um 11:33
Gammatester - Do 27.06.13 09:45
Christian213 hat folgendes geschrieben : |
Die Frage die sich mir stellt ist: Wieso muss ich eine untypisierte Pointer-Variable definieren und diese dann de-referenziert übergeben? |
Mußt Du das wirklich? Das ist mM die gleiche Situation wie zB bei system.move, also sollte doch eigentlich auch
regist.ReadBinaryData(Value, Buffer[0], bytesRead); funktionieren.
Martok - Do 27.06.13 09:47
Hi!
Mein Vorschlag wäre erstmal:
Delphi-Quelltext
1: 2:
| SetLength(Buffer, bytesRead); regist.ReadBinaryData(Value, Buffer[0], bytesRead); |
Hintergrund: untypisierte Parameter sind sowas ähnliches wie Pointer, die auf der andern Seite direkt dereferenziert werden. Du willst hier also die das erste Element angeben. Bei dynamischen Arrays liegt das aber grade nicht an der Stelle, wo die Variable ist: wie bei Strings ist "Buffer" erstmal nur ein Zeiger (mit angehängter Längenangabe) auf einen Speicherbereich, wo dann die echten Daten sind.
Bei einem Array mit fester Länge würde das übrigens funktionieren, da dort die Variable direkt den Speicherbereich bezeichnet und damit immer mit dem ersten Element identisch ist, ohne die weitere Ebene Verpointerung dazwischen.
Warum funktioniert dein Pointer?
Wie erwähnt ist Buffer ein Zeiger auf einen Speicherbereich.
Pointer() (nicht
Ptr() oder
@) ist nur ein Typecast, du tust also nichts weiter, als dem Zeiger in
Buffer folgen. Genau das also was passiert, wenn du auf das erste Element zugreifst.
An der Stelle mag ich FPC auch wieder, Delphi würde den Code vermutlich anstandslos ausführen, aber er würde nicht funktionieren. Durch den SegFault weißt du wenigstens direkt, dass du irgendwo wild im Speicher rumschreibst ;-)
... und da war der
Gammatester schneller :zwinker:
Christian213 - Do 27.06.13 10:24
Hallo,
Danke für die Antworten.
Ihr habt natürlich Recht: Es geht auch mit Buffer[0].
Der Unterschied in der Adressierung war mir irgendwie gerade entfallen.
So macht das Ganze auch für mich wieder Sinn.
Gruß
Christian
jaenicke - Fr 28.06.13 21:53
Martok hat folgendes geschrieben : |
An der Stelle mag ich FPC auch wieder, Delphi würde den Code vermutlich anstandslos ausführen, aber er würde nicht funktionieren. Durch den SegFault weißt du wenigstens direkt, dass du irgendwo wild im Speicher rumschreibst ;-) |
Das hat nichts mit FPC oder Delphi zu tun, die Schutzverletzung kommt von Windows und das auch nur zufällig, weil der Speicher an der Stelle bekannt ist als nicht beschreibbar...
Setze vorher einfach mal den Pointer auf einen Bereich, der nicht ungültig ist und es kommt auch bei FPC keine Fehlermeldung.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!