"file" type ... Zugriff auf Interna (HANDLE und Konsorten)?
"file" type ... Zugriff auf Interna (HANDLE und Konsorten)?
Hi allseits,
jeder von uns hat sicher Sequenzen wie
var F: file
Assign(F,....)
Reset(F,...)
Read(F,....)
Close(F,...)
1000 mal verwendet. Jetzt bin ich beim Debuggen eher zufällig auf eine unbeantwortete Frage gestoßen: laut Debugger hat F, oder besser der Typ "file", eine innere Struktur. Da gibt es z.B. HANDLE, MODE, RECSIZE usw. Es scheint aber, dass Code wie
if F.Handle <> 0
nicht durch den Compiler kommt: "illegal qualifier".
Zwei Fragen:
- wieso ist das so, oder habe ich etwas übersehen
- ist es auf Umwegen möglich, "file" seine Geheimnisse abzuluchsen (ich bin besonders scharf auf HANDLE)
Gruss Armin.
jeder von uns hat sicher Sequenzen wie
var F: file
Assign(F,....)
Reset(F,...)
Read(F,....)
Close(F,...)
1000 mal verwendet. Jetzt bin ich beim Debuggen eher zufällig auf eine unbeantwortete Frage gestoßen: laut Debugger hat F, oder besser der Typ "file", eine innere Struktur. Da gibt es z.B. HANDLE, MODE, RECSIZE usw. Es scheint aber, dass Code wie
if F.Handle <> 0
nicht durch den Compiler kommt: "illegal qualifier".
Zwei Fragen:
- wieso ist das so, oder habe ich etwas übersehen
- ist es auf Umwegen möglich, "file" seine Geheimnisse abzuluchsen (ich bin besonders scharf auf HANDLE)
Gruss Armin.
Zuletzt geändert von Nimral am Sa 28. Nov 2015, 23:17, insgesamt 1-mal geändert.
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Bin einen kleinen Schritt weiter. Ich habe die Definition des Typs "File" bzw. "FileRec" gefunden:
http://www.freepascal.org/docs-html/rtl ... lerec.html
FileRec ist also ein packed Record. Handle ist ein THandle, THandle ist ein LongInt. Der Vergleich <> 0, den der Compiler in meinem Code mit "Illegal Qualifier" anmäkelt ist also eigentlich zulässig. Hm.
Die Fehlermeldung "Illegal Qualifier" ist ebenfalls dokumentiert:
http://www.freepascal.org/docs-html/3.0 ... rse62.html
Error: Illegal qualifier
One of the following is happening :
You’re trying to access a field of a variable that is not a record.
You’re indexing a variable that is not an array.
You’re dereferencing a variable that is not a pointer.
Trifft alles m.E. nicht zu. Gut, ich habe als Workaround den packed Record Typen, und kann jetzt vermutlich einen Pointer auf FileRec auf die Adresse von F mappen, dann sollte ich auf die Felder zugreifen können. Aber warum hat mein Code den Compiler nicht passiert?
Wer hat eine Erklärung?
Thx
Armin.
http://www.freepascal.org/docs-html/rtl ... lerec.html
FileRec ist also ein packed Record. Handle ist ein THandle, THandle ist ein LongInt. Der Vergleich <> 0, den der Compiler in meinem Code mit "Illegal Qualifier" anmäkelt ist also eigentlich zulässig. Hm.
Die Fehlermeldung "Illegal Qualifier" ist ebenfalls dokumentiert:
http://www.freepascal.org/docs-html/3.0 ... rse62.html
Error: Illegal qualifier
One of the following is happening :
You’re trying to access a field of a variable that is not a record.
You’re indexing a variable that is not an array.
You’re dereferencing a variable that is not a pointer.
Trifft alles m.E. nicht zu. Gut, ich habe als Workaround den packed Record Typen, und kann jetzt vermutlich einen Pointer auf FileRec auf die Adresse von F mappen, dann sollte ich auf die Felder zugreifen können. Aber warum hat mein Code den Compiler nicht passiert?
Wer hat eine Erklärung?
Thx
Armin.
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Der Dateizugriff mit Assign, Reset, Read, Close, etc. wird als Bestandteil der Sprache Pascal gewertet; daher sind die file-Typen für den Entwickler transparant d.h. nicht zugreifbar. Wenn du ein Dateihandle benötigtst, kannst du immer noch die Funktionen FileOpen() nutzen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Code: Alles auswählen
var
f1: file of byte;
begin
assignfile(f1,'test.txt');
writeln(tfilerec(f1).handle,' ',tfilerec(f1).handle = unusedhandle);
reset(f1);
writeln(tfilerec(f1).handle,' ',tfilerec(f1).handle = unusedhandle);
closefile(f1);
writeln(tfilerec(f1).handle,' ',tfilerec(f1).handle = unusedhandle);
end;
Code: Alles auswählen
-1 TRUE
8 FALSE
8 FALSE
Was möchtest du konkret erreichen?
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Dank euch für die hilfreichen Antworten. Ich finde es sowohl unnötig als auch inkonsequent, die Innereien des Filerec vor dem Entwickler zu verbergen. Aber gut.
Ich habs inzwischen auch gelöst, etwas komplizierter: einen Pointer pF = ^FileRec definiert, und ihn mit pF := @F auf mein File Handle gemappt, danach kann ich die pF^.Handle lesen, prima.
Was ich erreichen wollte: Ich habe öfters Konstrukte wie diese:
Innerhalb des Try Blocks kann alles mögliche schief gehen, und wenn ich anfange, jeden einzelne Codesequenz mit eigenen try ... except und try ... finally Blöcken abzusichern entsteht ein fürchterliches Dickicht. Mache ich es nicht, komme ich immer wieder in Teufels Küche: verwaiste File Handles blockieren Dateien, und es gibt Speicherlecks. Das Problem ist, dass der Freemem Block nicht erkennen kann, wo die Exception ausgelöst wurde. Handles (um bei denen zu bleiben) können beim Aufräumen also offen sein oder auch nicht, je nachdem wie weit der Code gekommen ist. Manches macht Pascal von selber zu, wenn das Ende der Routine erreicht wurde, aber erstens kann man sich nicht drauf verlassen, und zweitens fand ich bisher keine vollständige Dokumentation dazu, was genau automatisch wann freigegeben wird. Das gilt für Handles ebenso wie für dynamischen Speicher oder das Zerstören von Objekten. Ich möchte auch den Lesern meines Codes, die nach mir kommen, nicht zumuten, dass sie wissen müssen, was Pascal automatisch aufräumt und was nicht, um meinen Code zu verstehen. Das gilt auch und gerade bei Objekten: manche räumen sich sauber wieder ab, wenn die Routine beendet wurden, und bei manchen muss man selber irgendeine Free oder Destroy Routinen aufrufen. Hinweise dazu in den Dokus finden sich überaus spärlich.
Daher bin ich dazu übergegangen, im Finally konsequent alles zu zu machen oder freizugeben, was ich davor irgendwo aufgemacht habe, selbst wenn ich dazu ein paar Zeilen unnützen Code mehr schreiben muss. Dazu muss ich z.B. nachsehen, ob ein Handle auch geöffnet wurde, weil sonst der finally Code seinerseits wieder in Exceptions läuft.
also:
Speicherzeiger gebe ich im finally Block frei, wenn sie nicht mehr NIL sind. Handles sind noch offen wenn sie >0 sind. Bisher bin ich mit dieser Methodik ganz gut gefahren.
Und natürlich würde mir nicht im Traum einfallem, die Handles oder Adressen beschreiben zu wollen, ich muss sie nur lesen, um zu sehen ob sie verwendet wurden, und das sollte kein Problem sein
.
Armin.
Ich habs inzwischen auch gelöst, etwas komplizierter: einen Pointer pF = ^FileRec definiert, und ihn mit pF := @F auf mein File Handle gemappt, danach kann ich die pF^.Handle lesen, prima.
Was ich erreichen wollte: Ich habe öfters Konstrukte wie diese:
Code: Alles auswählen
Try
... haufenweise code, auch mal dynamisch Speicher reservieren ...
GetMem oder New ...
Assign(F,....)
Rewrite(F,..)
For ... to
Blockwrite(F,...)
Close(F);
... haufenweise weiterer code
Finally
... der solls richten wenn etwas schief geht
Close(F)
Freemem oder Dispose ...
Daher bin ich dazu übergegangen, im Finally konsequent alles zu zu machen oder freizugeben, was ich davor irgendwo aufgemacht habe, selbst wenn ich dazu ein paar Zeilen unnützen Code mehr schreiben muss. Dazu muss ich z.B. nachsehen, ob ein Handle auch geöffnet wurde, weil sonst der finally Code seinerseits wieder in Exceptions läuft.
also:
Code: Alles auswählen
finally
if pF^.Handle > 0 then close(F); // Datei ist noch offen
if pBuffer <> NIL then FreeMem(pBuffer,READ_BUFFER_SIZE) // Speicher wurde reserviert
Und natürlich würde mir nicht im Traum einfallem, die Handles oder Adressen beschreiben zu wollen, ich muss sie nur lesen, um zu sehen ob sie verwendet wurden, und das sollte kein Problem sein

Armin.
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Thx, das ist nützlich, macht meinen Code noch einfacher. Ich hatte irgendwie nicht mitbekommen, dass die guten alten Open und Close Befehle irgendwann auch Handle basierte Zwillinge bekommen haben. Wenn ich auf die umsteige, habe ich immer ein Handle zur Verfügung. Ich denke, so mache ich es in Zukunft.Socke hat geschrieben:Der Dateizugriff mit Assign, Reset, Read, Close, etc. wird als Bestandteil der Sprache Pascal gewertet; daher sind die file-Typen für den Entwickler transparant d.h. nicht zugreifbar. Wenn du ein Dateihandle benötigtst, kannst du immer noch die Funktionen FileOpen() nutzen.
Thx,
Armin.
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Das stimmt leider nicht, siehe mein Beispiel. tfilerec(f1).handle ist nach close() immer noch 8.Nimral hat geschrieben: Speicherzeiger gebe ich im finally Block frei, wenn sie nicht mehr NIL sind. Handles sind noch offen wenn sie >0 sind.
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Dann muss man eben nachhelfen:mse hat geschrieben:Das stimmt leider nicht, siehe mein Beispiel. tfilerec(f1).handle ist nach close() immer noch 8.Nimral hat geschrieben: Speicherzeiger gebe ich im finally Block frei, wenn sie nicht mehr NIL sind. Handles sind noch offen wenn sie >0 sind.
Code: Alles auswählen
close(f1);
f1 := 0; // wenn der Code hier her kommt, ist der close ohne Exception gelaufen
Armin.
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
0 ist auf Linux ein gültiges Filehandle (StdIn).
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Guter Hinweis, aber für mich ohne Relevanz.mse hat geschrieben:0 ist auf Linux ein gültiges Filehandle (StdIn).
Gegenfrage: wie machst Du das Error Handling?
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: "file" type ... Zugriff auf Interna (HANDLE und Konsorte
Ich kann mich nicht mehr erinnern, wann ich das letzte mal assignfile(), reset() und Konsorten verwendet hätte.
Ansonsten wie du, Objekt-Instanzen mit "nil" initialisieren und mit free() abräumen. Filehandle sind meistens in TStream gekapselt und müssen nicht gesondert behandelt werden.
Ansonsten wie du, Objekt-Instanzen mit "nil" initialisieren und mit free() abräumen. Filehandle sind meistens in TStream gekapselt und müssen nicht gesondert behandelt werden.