Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Generic <T>, injected DLL, was aus Speicher auslesen? (https://www.delphipraxis.net/178761-generic-t-injected-dll-aus-speicher-auslesen.html)

MrLolli 25. Jan 2014 17:23


Generic <T>, injected DLL, was aus Speicher auslesen?
 
Hallo,

kurze Frage, ist es möglich mittels <T> etwas aus dem Speicher auszulesen, ohne ReadProcessMemory? Da ich mich im gleichen Prozess befinde möchte ich natürlich darauf verzichten.

Normalerweise würde es ja bei Integern z.B. so aussehen:

Delphi-Quellcode:
i := PInteger($123456)^
Wie würde ich bei einer Funktion mit T vorgehen? Ist mein Vorhaben überhaupt so einfach realisierbar?

Beispiel:

Delphi-Quellcode:
function GetMem<T>(Offset: NativeUInt): T;
begin

end;
Gruß

edit: Habe es schon gelöst bekommen, einfacher als gedacht :)

Delphi-Quellcode:
function GetMem<T>(Offset: NativeUInt): T;
type
  PT = ^T;
begin
  result := PT(Offset)^
end;

himitsu 25. Jan 2014 18:35

AW: Generic <T>, injected DLL, was aus Speicher auslesen?
 
Jain, das ist fast möglich, oder kann Delphi inzwischen doch schon generischen Prozeduren?
Und wenn nicht, dann solltest du im Profil, oder nächstes Mal im Post, mit angeben, für welchen Compiler du etwas suchst.

Aber wenn du deine Funktion in eine Klasse verlagerst, wo es auch eine Klassenmethode sein kann, welche als Static im Kompilat praktisch genauso auferufen wird, wie eine entsprechende "normale" Funktion, dann ginge es.


Wieso eigentlich Offset?
OK, zum nil wäre es ein Offset, aber im Prinzip gibst du doch direkt deine Adresse an.

Delphi-Quellcode:
class function TMyClass.GetMem<T>(Addr: Pointer): T; // Nja, oder zumindestens auch nochmal mit NativeUInt überladen.
type
  PT = ^T; // oder als public/private type direkt oben in der Klassendefinition
begin
  Result := PT(Offset)^;
end;

// geht eventuell auch "direkt"

class function TMyClass.GetMem<T>(Addr: Pointer): T;
begin
  Result := T(Offset^);
end;
Nur wozu soll das Ganze gut sein?

Ohne z.B. auch noch eine Typ-Konvertierung (ala Byte zu Integer oder String), ist das doch etwas "umständlich"?
Also im Gegensatz zum direkten Cast?
Vorallem ohne "inline" sind hier nun unnötige Codesprünge und bei Typen womöglich auch noch unnötige Speicheroperationen. (Referenzzählung von String und Interface, oder gar komplette Kopien, wie z.B. beim WideString)


Delphi-Quellcode:
i := PInteger($123456)^;

i := {TMyClass.}GetMem<Integer>($123456);

MrLolli 25. Jan 2014 18:44

AW: Generic <T>, injected DLL, was aus Speicher auslesen?
 
Hi himitsu,

Zitat:

Aber wenn du deine Funktion in eine Klasse verlagerst, wo es auch eine Klassenmethode sein kann, welche als Static im Kompilat praktisch genauso auferufen wird, wie eine entsprechende "normale" Funktion, dann ginge es.
dessen bin ich mir bewusst, meine wirkliche Funktion steckt ja auch in einer Klasse und sieht etwas anders aus ;)
Ich lese praktisch ein Array eines anderen Programms aus. In diesem Array sind Pointer die dann eben auf den eigentlichen Wert zeigen, und der kann unterschiedlich groß sein. Momentan kann ich damit ganz komfortabel darauf zugreifen.

Steckt man das obige Beispiel so in eine Klasse sollte es ja keine Probleme geben.

edit: oh ein edit

Delphi-Quellcode:
class function TMyClass.GetMem<T>(Addr: Pointer): T;
begin
  Result := T(Offset^);
end;
Funktioniert so leider nicht. NativeUInt habe ich so nur im Beispiel verwendet, ich gebe in Wirklichkeit den Index des Array an.

Gruß

himitsu 25. Jan 2014 18:52

AW: Generic <T>, injected DLL, was aus Speicher auslesen?
 
Zitat:

Zitat von MrLolli (Beitrag 1245351)
Steckt man das obige Beispiel so in eine Klasse sollte es ja keine Probleme geben.

Joar.

Ach ja, ich hatte meinen letzten Beitrag in der Zwischenzeit nochmal bearbeitet ... war wohl nur etwas langsam dabei. :stupid:


Und zum Array:
Delphi-Quellcode:
type
  // diese Array-Typen gibt es manchmal auch vordefiniert (z.B. PByte für Array[] of Byte)
  // manche Pointer-Typen besitzen auch schon eine integrierte Pointer-Arithmetik, wo man sich das Array sparen kann (z.B. PAnsiChar)
  TIntegerArray: array[0..0] of Integer;
  PIntegerArray: ^TIntegerArray;

var
  MyArr: PIntegerArray;

MyArr := Pointer($12345678);
for i := 0 to 10 of
  ShowMessage(IntToStr( MyArr[i] ));
Das entspricht quasi einem
Delphi-Quellcode:
var
  MyPnt: NativeUInt;

MyPnt := $12345678;
for i := 0 to 10 of
  ShowMessage(IntToStr( PInteger(MyPnt + i * SizeOf(Integer))^ )); // wobei den Offset Delphi auch automatisch berechnen kann => siehe oben

MrLolli 25. Jan 2014 18:57

AW: Generic <T>, injected DLL, was aus Speicher auslesen?
 
Da sehe ich nun das Problem das auch int64 Werte vorhanden sind, daher gefiel mir der Generic eigentlich am Besten.
Wären alles 4 Byte Werte, wäre es ja halb so wild und man könnte schnell 'umcasten'.

Vorher habe ich mir den Pointer zum Wert zurückgeben lassen und konnte dann einfach mit PInteger(Pointer)^ den Wert auslesen, optisch finde ich den Generic aber besser.
Nur fraglich ob es von der Leistung her auch so toll ist, aber soll mir in einem nur-für-mich Projekt eigentlich egal sein ;)

himitsu 25. Jan 2014 19:12

AW: Generic <T>, injected DLL, was aus Speicher auslesen?
 
Wieso sollte Int64 ein Problem sein?
In deinem Generic machst du doch genau das Selbe, nur halt etwas umständlicher weggekapselt. :zwinker:

Du castest ja nicht den "Inhalt" des Pointers, welcher in Win32 zufällig 4 Byte ist,
sondern das, worauf der Pointer zeigt und da ist die Größe egal.

Ein untypisierter Pointer hat quasi eine Größe von 0 Byte und beim Cast auf andere Typen wird dort keine Größenprüfung vom Compier vorgenommen.

MrLolli 25. Jan 2014 19:20

AW: Generic <T>, injected DLL, was aus Speicher auslesen?
 
Ah verstehe ;)

Finde dennoch es sieht mit Generics ein wenig hübscher und übersichtlicher aus, da ich von sehr vielen Stellen aus darauf zugreife. Denke einen allzu großen Performance-Verlust sollte es da nicht geben, oder? Zumindest sieht der generierte asm Code dazu ganz sauber aus.

Wobei es mir eh nicht um jede Nanosekunde geht. ^^

himitsu 25. Jan 2014 21:03

AW: Generic <T>, injected DLL, was aus Speicher auslesen?
 
Wenn du die Funktion als inline deklarierst und der Kompiler in der Lage ist, den Code auch direkt einzubinden, dann könnte es sein, daß der Compiler Vieles von der Funktion wegopimiert.

Delphi-Quellcode:
type
  TMyClass<T> = class
  public type
    PT = ^T; // muß natürlich public sein, damit es an der aufrufenden Stelle verfügbar ist
  public
    class function GetMem<T>(Offset: NativeUInt): T; static; inline;
  end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:42 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