![]() |
Woher weiß ich die Puffergröße für einen Aufruf?
Ich habe eine WinApi-Routine die mir einen String gibt. Man übergibt hierbei immer einen Zeiger auf das erste Zeichen und wie groß der bereitgestellte Puffer ist. Die Puffergröße ist immer ein in/out (Delphi-Sprech: "var-Parameter").
Bislang kannte ich das so dass man erst einmal
Delphi-Quellcode:
und eine Pufferlänge von 0 angibt, hierauf ein
nil
Delphi-Quellcode:
zurückbekommt und im var-Parameter drinsteht wie groß er den Puffer gerne hätte. Beispiel:
ERROR_INSUFFICIENT_BUFFER
Delphi-Quellcode:
GetTokenInformation(
processToken, TTokenInformationClass.TokenUser, nil, 0, bufferLength ); if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) then RaiseLastOSError(); SetLength(buffer, bufferLength); Win32Check( GetTokenInformation( processToken, TTokenInformationClass.TokenUser, buffer, bufferLength, bufferLength ) ); Ich habe nun ein Problem mit dem Aufruf ![]() Die Doku stimmt: Wenn der Puffer zu klein ist gibt der Aufruf
Delphi-Quellcode:
zurück und
False
Delphi-Quellcode:
liefert
GetLastError()
Delphi-Quellcode:
. Aber der Ausgabeparameter wird nicht gesetzt. Ich weiß also immer noch nicht wie groß der Puffer sein muss.
ERROR_INSUFFICIENT_BUFFER
Rein akademisch betrachtet: Wie muss man das richtig machen? Eine Schleife welche den Puffer so lange verdoppelt bis es irgendwann mal gepasst hat ist ja wirklich nicht schön... :| |
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Zitat:
Warum man die API an dieser Stelle so schlecht designed hat, erschließt sich mir allerdings auch nicht. An anderer Stelle ist es nachvollziehbar. Zum Beispiel immer dann, wenn dynamische Daten vorliegen, die sich "schnell" ändern (Prozessliste, etc). Dort macht es keinen Sinn eine feste Größe zurückzugeben, da sich diese beim zweiten Aufruf bereits wieder geändert haben kann. Mit dem Verdoppeln des Buffers hat man im Zweifelsfalle immer noch ein wenig Spielraum nach oben. |
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Hab auch grad mal rumprobiert und MSDN hat leider wirklich recht :|
Reservier einfach beim 1. Versuch schon halbwegs viel. Wenn du 500 Bytes, oder vllt. sogar 1KB reservierst solltest du ja zu 99% keine Probleme haben. Und 1KB an Speicher ist ja heutzutage nix mehr und du kannst ihn ja kurz darauf ja auch wieder freigeben bzw verkleinern. Verbraucht mehr Speicher aber ist evtl. schneller als verdoppeln (je nachdem mit welchem Wert du anfängst) und mehrmals zu probieren. |
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Danke für den seelischen Beistand, dann ist das wohl wirklich etwas komisch.
Ich nehme einfach 32 KB, die (momentan) maximale Pfadgröße :stupid: |
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Herzlichen Glückwunsch. Du hast die Ungereimtheiten zwischen verschiedenen Generationen von Windows-Schnittstellen für dich entdeckt. Das ist ein wunderbar erbauliches Thema welches zu graumeliertem Haar und wunderbaren Falten führen kann.
Und alle arbeiten mit ERROR_INSUFFICIENT_BUFFER :mrgreen: Zitat:
Zitat:
Ansonsten hat Zacherl deine Frage ja schon beantwortet. Ja, es ist die einzige sinnvolle Methode. Statt verdoppeln kannst du natürlich auch immer einen festen Wert draufschlagen. Und natürlich kannst du auch versuchen auf den von dir unterstützten Systemen einen guten Basiswert zu ermitteln, um die Anzahl der Allozierungen klein zu halten. |
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Zitat:
Vielleicht auch ganz gut, somit wird es nie langweilig. Danke nochmal allen für die Hilfe :-) |
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Zitat:
Die Obergrenze stammt daher, daß ![]() Während ehemals Windows NT UCS2 meinte wenn Unicode draufstand (also exakt ein WideChar pro Codepunkt), erweitern moderne Windowsversionen dies auf UTF-16, wodurch Zeichen außerhalb des ![]() Ein Pfadname kann also durchaus kürzer sein als es die Länge in WideChar vermuten lassen würde. Das eigentliche Thema ist aber die Erweiterung der Pfadnamen im Kernelmodus. Haste beispielsweise die Datei C:\bootmgr, wird das bei der Benutzung von langen Pfadnamen laut ![]() ![]() ![]() Die eigentliche Obergrenze ist also etwas schwammig, weil sie davon abhängt die lang der Gerätename im Namensraum des Objektmanagers ist. MSDN weist auch drauf hin: Zitat:
![]() ![]() |
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Es sind nicht nur unterschiedliche Windows Versionen, warum die API nicht konsistent ist. Teilweise liegt es auch daran, dass unterschiedliche Teams an dem gleichen System gearbeitet haben.
|
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Im Prinzip kann man auch eine Repeat-Schleife um den Aufruf machen, wenn sich die Puffergröße zu schnell ändern könnte.
Mit Len=0 die Schleife beginnen, oder gleich blind schonmal paar Bytes bereitstellen, und wenn nicht groß genug, dann die Schleife mit größerem Speicher durchlaufen. Im Normalfall reichen ja auch zwei aufeinanderfolgende Aufrufe mit nil+0 und dann nochmal mit @buff+len, aber es gibt auch APIs, die zwar irgendein ERROR_INSUFFICIENT_BUFFER liefern, wenn zu klein, es aber nicht erlauben, dass man NIL+0 rein gibt, um erstmal nur nach der Größe zu fragen. Bezüglich der erwähnten Prozesslisten kann es auch sein, dass der Aufruf dennoch erfolgreich ist, auch wenn de Puffer zu klein war. (gilt auch für andere APIs, die 'ne Art Record-Array liefern) Da bekommt man dann einfach nur die x Prozesse aufgelistet, die in den Puffer passen. Oftmals kann man bei sowas dann aber auch noch einen Offset reingeben, um in Folgeaufrufen weitere Prozesse abzufragen. Also z.B. statt alle 200.000 auf Einmal einfach immer nur je 1000, bis man dann Alle hat. PS: MAX_PATH ist zwar 260, aber eigentlich ist der "maximale Pfad" nur 256 inkl. der abschließenden #0. (das DRIVE "X:\" gehört ja eigentlich nicht zum PATH, im jeweiligen Gerätetreiber) |
AW: Woher weiß ich die Puffergröße für einen Aufruf?
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz