Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi PChar wiederverwenden? (https://www.delphipraxis.net/155104-pchar-wiederverwenden.html)

moelski 8. Okt 2010 12:41


PChar wiederverwenden?
 
Moin !

Ich habe da ein Stück Code was ich zum dynamischen Auslesen von Performance Countern nutzen möchte:
Delphi-Quellcode:
var _IndexA, _IndexB,
    _BufferSize        : LongWord;
    _Res               : PChar;
    _ValueName         : String;
    _Status            : PDH_STATUS;
begin
  _IndexA := 238;    // (Processor) : 238
  _IndexB := 6;      // (% Processor Time) : 6

  _BufferSize := 100;
  GetMem(_Res, _BufferSize);
  _Status := PdhLookupPerfNameByIndexW(Nil, _IndexA, _Res, _BufferSize);
  if _Status = ERROR_SUCCESS then begin
    Log('ValueName : ' + PChar(_Res));
    _ValueName := PChar(_Res);
  end else
    Log('Status   : ' + IntToHex(_Status, 8));
  FreeMem(_Res);

  _res := NIL;

  GetMem(_Res, _BufferSize);
  _Status := PdhLookupPerfNameByIndexW(Nil, _IndexB, _Res, _BufferSize);
  if _Status = ERROR_SUCCESS then begin
    Log('ValueName : ' + PChar(_Res));
  end else
    Log('Status   : ' + IntToHex(_Status, 8));
Nun bekomme ich über _Res den ermittelten Namen zurück in einem Buffer.
Beim ersten Aufruf klappt es auch. Aber beim zweiten kriege ich den Fehler das der Buffer zu klein wäre.
Das kann aber nicht sein, denn wenn ich nur den unteren Teil verwende klappt das wunderbar.

Es muss also an meiner Verwendung von _Res (PChar) liegen. Nur was ist da falsch?
Ob mit oder ohne _res := NIL spielt übrigens keine Rolle.

moelski 8. Okt 2010 12:48

AW: PChar wiederverwenden?
 
Moin !

Kanns mir selber beantworten ...

PdhLookupPerfNameByIndexW beeinflusst die Buffersize ... Und die ist danach zu klein für den zweiten Wert.

:roll:

p80286 8. Okt 2010 12:51

AW: PChar wiederverwenden?
 
Das riecht doch sehr danach, das _Buffersize nach der Rückkehr die Länge des Strings enthält. Also setz es neu und es sollte klappen.
Ich hab die Doku nur überflogen aber vllt. geht es auch so:
Delphi-Quellcode:
_res := NIL;
_Buffersize:=0;
_Status := PdhLookupPerfNameByIndexW(Nil, _IndexB, _Res, _BufferSize);
GetMem(_Res, _BufferSize);
_Status := PdhLookupPerfNameByIndexW(Nil, _IndexB, _Res, _BufferSize);
Gruß
K-H

zu spät (sniief)

moelski 8. Okt 2010 12:53

AW: PChar wiederverwenden?
 
Zitat:

zu spät (sniief)
Sorry aber dennoch danke :thumb:

himitsu 8. Okt 2010 13:01

AW: PChar wiederverwenden?
 
Zitat:

Zitat von p80286 (Beitrag 1054522)
Das riecht doch sehr danach,

es riecht nicht nur ... das stickt schon richtig :mrgreen:

Zitat:

Zitat von siehe MSDN/PSDK
Size of the szNameBuffer buffer, in TCHARs. If zero on input, the function returns PDH_MORE_DATA and sets this parameter to the required buffer size. If the buffer is larger than the required size, the function sets this parameter to the actual size of the buffer that was used. If the specified size on input is greater than zero but less than the required size, you should not rely on the returned size to reallocate the buffer.

also schreib bitte
Delphi-Quellcode:
_BufferSize div SizeOf(Char)
, denn da wird nicht die Größe in Byte angegeben.

Heißt also, da du mit Delphi 2010 arbeitest, daß die 100 = 100 Zeichen aka 200 Byte entspricht.
also bei 50 bis 100 Zeichen würdest du dir einen Bufferoverrun einhandeln :warn:

OK, da es hier ein Var-Parameter ist, wäre es wohl einfacher, wenn du beim GetMem
Delphi-Quellcode:
* SizeOf(Char)
rechnest.


[add]
wobei ich auch gern mal einen anderen Weg geh :angel2:
Delphi-Quellcode:
var _Index, _BufferSize : LongWord;
    _ValueName : String;
    _Status : PDH_STATUS;
begin
  _Index := 238; // (Processor) : 238
  _BufferSize := 0;
  PdhLookupPerfNameByIndex(Nil, _Index, Nil, _BufferSize);
  SetLength(_ValueName, _BufferSize - 1);
  _Status := PdhLookupPerfNameByIndex(Nil, _Index, PChar(_ValueName), _BufferSize);
  if _Status = ERROR_SUCCESS then
    Log('ValueName : ' + _ValueName)
  else
    Log('Status : ' + IntToHex(_Status, 8));

  _Index := 6; // (% Processor Time) : 6
  _BufferSize := 0;
  PdhLookupPerfNameByIndexW(Nil, _Index, Nil, _BufferSize);
  SetLength(_ValueName, _BufferSize - 1);
  _Status := PdhLookupPerfNameByIndexW(Nil, _Index, PChar(_ValueName), _BufferSize);
  if _Status = ERROR_SUCCESS then
    Log('ValueName : ' + _ValueName)
  else
    Log('Status : ' + IntToHex(_Status, 8));
Wenn du noch mehr solcher Werte ausließt, dann würde ich das Auslesen lieber in eine Funktion packen.

PS: du nutzt PChar (dynamisch) und PdhLookupPerfNameByIndexW (statisch) zusammen :warn:
entweder:
PAnsiChar + ...A
PWideChar + ...W
PChar + ...

Unter Anderem sowas ist für viele Fehler verantwortlich, welche es mit der Ansi-Unicode-Umstellung seit Delphi 2009 gibt.

moelski 8. Okt 2010 13:04

AW: PChar wiederverwenden?
 
Nich schlagen 8-)
Ich habs ja noch früh genug selber gemerkt :stupid:

himitsu 8. Okt 2010 13:26

AW: PChar wiederverwenden?
 
Keine Sorge ... hab meinen Baseballschläger eh noch (im Laden) vergessen.

Und das "in TCHARs" nicht vergessen.

moelski 8. Okt 2010 13:28

AW: PChar wiederverwenden?
 
Inzwischen klappt alles:
Code:
[14:26:17] : \\XYZ\Processor(0)\% Processor Time
[14:26:17] : Value : 12,5
[14:26:17] : \\XYZ\Processor(1)\% Processor Time
[14:26:18] : Value : 6,1
[14:26:18] : \\XYZ\Processor(_Total)\% Processor Time
[14:26:18] : Value : 3,1
:)

himitsu 8. Okt 2010 13:59

AW: PChar wiederverwenden?
 
12,5 + 6,1 ist für mich aber ~9,3 :roll:

moelski 8. Okt 2010 14:15

AW: PChar wiederverwenden?
 
Hast schon Recht, aber ich habe zwischen den Messungen je 500ms Pause gehabt.
Insofern passt deine Rechnung nicht :wink:


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:37 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz