PtrUint auf PChar

Für Fragen von Einsteigern und Programmieranfängern...
wennerer
Beiträge: 609
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

PtrUint auf PChar

Beitrag von wennerer »

Hallo,
wie ich mich mit diesen Beitrag viewtopic.php?t=16605 befasst habe bin ich auf eine interessante Datei gestossen die bei Lazarus mitgeliefert wird. Sie befindet sich bei mir im Verzeichnis ...../fpcsrc/tests/test/units/system/ und heißt: tres3.pp. Wenn man die ein kleinwenig anpasst und als Programm laufen lässt spuckt es die einkompilierten Resourcen in der Konsole aus.
Tres3.png
Tres3.png (145.62 KiB) 4811 mal betrachtet
Ich bin leider weit dovon entfernt das Programm komplett zu verstehen, wäre aber schon sehr glücklich wenn ich die Zeile

Code: Alles auswählen

if Is_IntResource(ResourceName) then
    writeln('    Name: ',PtrUint(ResourceName)) 
verstehen würde. Was ist eine IntResource? Und was macht PtrUInt mit einem PChar? Ich habe natürlich im Wiki viel gelesen aber kapiert hab ich leider nix.
Ist es möglich den PChar "ResourceName" in eine Stringvariable zu casten?
Kann es jemand so erklären das ich es verstehen kann ? :oops:

Viele Grüße
Bernd
Dateianhänge
Tres3.zip
(27.87 KiB) 56-mal heruntergeladen

Benutzeravatar
Zvoni
Beiträge: 378
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: PtrUint auf PChar

Beitrag von Zvoni »

wennerer hat geschrieben: Mi 19. Feb 2025, 18:40 Was ist eine IntResource?
https://www.freepascal.org/docs-html/rt ... ource.html
Is_IntResource returns True if the resource type is internal (system predefined) resource or false if it is a user-defined resource type.
Verwendung von PtrUint:
Wenn ich den Code richtig lese:
Falls die Ressource NICHT eine (system) interne Ressource ist (sondern eine User-definierte Ressource), gib den Namen der Ressource aus (Else-Teil vom If)
Ist es eine interne Ressource, gib die Speicher-Adresse zurück. Ein "Writeln(Pointer(EinPChar));" geht nicht, und Writeln dereferenziert immer einen PChar (versucht es zumindest).
Könnte mir vorstellen, dass es eine Verteidigung gegen einen nicht dereferenzierbaren PChar ist (keine Ahnung)
Ist es möglich den PChar "ResourceName" in eine Stringvariable zu casten?
https://www.freepascal.org/docs-html/rt ... trpas.html

Code: Alles auswählen

Uses SysUtils;
var 
  p:PChar;
  s:String;
Begin
  p:='Ein Test';
  s:=strPas(p);
End;
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

wennerer
Beiträge: 609
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: PtrUint auf PChar

Beitrag von wennerer »

Hallo Zvoni,
also IntResource steht für Interne und nicht für integer. Da war ich wohl blind :shock: !
Dann verstehe ich auch die Funktion:

Code: Alles auswählen

function Is_IntResource(aStr : pchar) : boolean; {$ifdef SYSTEMINLINE}inline;{$endif}
begin
  Result:=((PtrUInt(aStr) shr 16)=0);
end;  
Aller Speicher unter 2hoch16 (also 1 Word) ist für interne Resourcen vorgesehen.
In der Referenz zu PtrUInt steht:
PtrUInt is an unsigned integer type which has always the same size as a pointer. When using integers which will be cast to pointers and vice versa, use this type, never the regular Cardinal type.
Mein Englisch ist jetzt nicht das Beste aber so wie ich das lese müsste PtrUInt doch nicht die Adresse sondern die Größe liefern oder wie muss ich das verstehen?
Kapiere ich nicht so wirklich.

Leider erzeugen alle TypCast's die ich probiert habe eine Speicherzugriffsverletzung. Ist es überhaupt möglich auf diesen Speicherbereich mit Pascal zuzugreifen?

Viele Grüße
Bernd

Mathias
Beiträge: 6926
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: PtrUint auf PChar

Beitrag von Mathias »

Ich habe gerade gesehen, das strPas ein Shortstring retour gibt, das könnte es einen Überlauft geben, wen der String länger als 255 Zeichen ist.

Ich mache es direkt.

Code: Alles auswählen

const
  ch: pchar = 'HelloWorld';
var
  s: string;

begin
  s := ch;
  WriteLn(s);
  s := s + '1234';
  WriteLn(s);
  WriteLn(ch);  
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wennerer
Beiträge: 609
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: PtrUint auf PChar

Beitrag von wennerer »

Naja, writeln geht schon. Aber ich möchte die Namen ja in eine Variable oder Stringlist etc. bringen.

Benutzeravatar
Zvoni
Beiträge: 378
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: PtrUint auf PChar

Beitrag von Zvoni »

Mathias hat geschrieben: Do 20. Feb 2025, 17:31 Ich habe gerade gesehen, das strPas ein Shortstring retour gibt, das könnte es einen Überlauft geben, wen der String länger als 255 Zeichen ist.

Ich mache es direkt.

Code: Alles auswählen

const
  ch: pchar = 'HelloWorld';
var
  s: string;

begin
  s := ch;
  WriteLn(s);
  s := s + '1234';
  WriteLn(s);
  WriteLn(ch);  
Genau hinschauen: ich nutze strpas aus Sysutils, nicht die von System.
Siehe auch link oben
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Benutzeravatar
Zvoni
Beiträge: 378
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: PtrUint auf PChar

Beitrag von Zvoni »

wennerer hat geschrieben: Do 20. Feb 2025, 17:25 Hallo Zvoni,
also IntResource steht für Interne und nicht für integer. Da war ich wohl blind :shock: !
Dann verstehe ich auch die Funktion:

Code: Alles auswählen

function Is_IntResource(aStr : pchar) : boolean; {$ifdef SYSTEMINLINE}inline;{$endif}
begin
  Result:=((PtrUInt(aStr) shr 16)=0);
end;  
Aller Speicher unter 2hoch16 (also 1 Word) ist für interne Resourcen vorgesehen.
In der Referenz zu PtrUInt steht:
PtrUInt is an unsigned integer type which has always the same size as a pointer. When using integers which will be cast to pointers and vice versa, use this type, never the regular Cardinal type.
Mein Englisch ist jetzt nicht das Beste aber so wie ich das lese müsste PtrUInt doch nicht die Adresse sondern die Größe liefern oder wie muss ich das verstehen?
Kapiere ich nicht so wirklich.

Leider erzeugen alle TypCast's die ich probiert habe eine Speicherzugriffsverletzung. Ist es überhaupt möglich auf diesen Speicherbereich mit Pascal zuzugreifen?

Viele Grüße
Bernd
Ptruint hat immer die gleiche Größe wie ein Zeiger, abhängig von der Platform.
Auf 64 bit OS ist es 64Bit gross, auf 32bit…..
Und das ist eben ein Typecast von Pchar, was ja auch ein zeiger ist.
Wenn du einen Pchar an writeln gibst, dereferenziert writeln diesen zeiger.
Mit dem cast kannst du aber die adresse mit writeln ausgeben, was eben mit Pointer nicht geht

Und wie kommst du auf 2 hoch 16?
Müsste doch 2 hoch 4 sein

EDIT: Schmarrn. Hast recht
Shr 16 heisst 16 bits nach rechts
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

wennerer
Beiträge: 609
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: PtrUint auf PChar

Beitrag von wennerer »

Hallo Zvoni,
Danke für die Antwort. Aber auch strpas aus Sysutils löst einen sigsev aus.
sigsev.png
sigsev.png (46.53 KiB) 4598 mal betrachtet
Viele Grüße
Bernd

PascalDragon
Beiträge: 958
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: PtrUint auf PChar

Beitrag von PascalDragon »

Ressourcen haben entweder String oder Integer Namen und/oder Typen. Dabei wird in beiden Fällen der gleiche Pascal Typ dafür verwendet (nämlich PChar), weswegen es die Funktion Is_IntResource() gibt, um zu unterscheiden was der PChar nun tatsächlich ist. Und ja, das Int in Is_IntResource steht tatsächlich für Integer, nicht Internal. Es hindert einen niemand daran selbst Ressourcen mit Integer Namen oder Typen anzulegen.
Und falls jemand fragt warum: das Ressourcensystem basiert auf dem Ressourcensystem von Windows, deswegen werden die Fähigkeiten von dem eben auch entsprechend für die anderen Plattformen abgebildet.
FPC Compiler Entwickler

Mathias
Beiträge: 6926
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: PtrUint auf PChar

Beitrag von Mathias »

Und ja, das Int in Is_IntResource steht tatsächlich für Integer, nicht Internal. Es hindert einen niemand daran selbst Ressourcen mit Integer Namen oder Typen anzulegen.
Da ist der Fall klar, das es knallt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wennerer
Beiträge: 609
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: PtrUint auf PChar

Beitrag von wennerer »

Hallo PascalDragon,
vielen Dank für deine Antwort. Ich habe es mir nun nochmal mit etwas Ruhe und dem Wissen das es Integer Namen gibt angesehen. Es werden in dem Programm zu erst einige Integer Namen gelesen bevor meine angelegten String Namen gelesen werden. Von daher ist mir jetzt klar warum alle Cast-Versuche eine Zugriffsverletzung ausgelöst haben.
Die Lösung ist damit natürlich ganz simpel (wie immer hinterher):

Code: Alles auswählen

if Is_IntResource(ResourceName) then
    writeln('    Name: ',PtrUint(ResourceName))
  else
   begin
    //writeln('    Name: ',ResourceName);
    debugln(ResourceName);
   end;  
Aber wie bringt man einen Integer in einen PChar?

Viele Grüße
Bernd

Mathias
Beiträge: 6926
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: PtrUint auf PChar

Beitrag von Mathias »

Aber wie bringt man einen Integer in einen PChar
Die Lösung hast du schon im Titlel.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wennerer
Beiträge: 609
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: PtrUint auf PChar

Beitrag von wennerer »

Was ginge wäre:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender : TObject);
var i : integer;
    P : PChar;
begin
 i := 33;
 P := PChar(i);
 caption := inttostr(ptruint(P));
end;   
Macht man es so?

Mathias
Beiträge: 6926
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: PtrUint auf PChar

Beitrag von Mathias »

Ich vermute ResNameProc verwendet einen PChar, weil es von C herkommt. C kennt kein Unterschied zwischen Char und Byte, dort ist einfach alles ein Char.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wennerer
Beiträge: 609
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: PtrUint auf PChar

Beitrag von wennerer »

Ja, da hast du wohl recht. Auch PascalDragons Beitrag zielt ja in diese Richtung.
Viele Grüße Bernd

Antworten