Initialisierung von Records [gelöst]

Für Fragen von Einsteigern und Programmieranfängern...
joe
Beiträge: 37
Registriert: Fr 28. Mai 2010, 15:47

Initialisierung von Records [gelöst]

Beitrag von joe »

Zu Zeiten von Turbo Pascal habe ich meine Records oft mit FillChar() auf 0 initialisiert.

Code: Alles auswählen

Procedure Tralala;
  var Bla: TBla;
  begin
  FillChar(Bla,SizeOf(Bla),#0)
  end;
Ein SetZero(Bla) wäre zwar deutlich schöner lesbar, aber man hatte sich daran gewöhnt (und beim versehentlichen vertauschen der letzten beiden Parameter meckert ja der Compiler, ganz im Gegensatz zum C Pendant memset()).

Wenn ich das jetzt dem FPC unterschiebe, dann nörgelt der mich an, da die Variable Bla zum Zeitpunkt der Übergabe an FillChar() nicht initialisiert sein. Der Grund dafür ist wohl, dass der erste Parameter von FillChar() als 'var' attributiert ist.
Mein Vorschlag, dies nach 'out' zu ändern hat Jonas Maebe abgelehnt (http://bugs.freepascal.org/view.php?id=17020):
It is not possible to do that, because "out" also automatically finalizes any automated types. That means that this would result in crashes if someone e.g. allocates memory for an array of ansistrings using getmem and then uses fillchar to initialize it to zero (because the "out" parameter would cause the random data in the getmem'ed block to be finalized).
This behaviour cannot be changed because of compatibility reasons.
Soweit akzeptiere ich das erst mal, verstehe sie aber noch nicht so ganz.
Automatisierte Typen sind offenbar Datentypen, deren Konstruktoren und Destruktoren automatisch gerufen werden (Strings und dyn. Arrays)? Kann man sich sowas eigentlich auch selbst definieren?
Ich war davon ausgagengan, dass das Attribut 'out' soviel bedeutet wie: Da kann man irgendwas Uninitialisiertes reinstecken und hinterher hat das einen gültigen Wert.

Doch was verwendet man denn jetzt anstelle von FillChar() ?
Zuletzt geändert von joe am So 25. Jul 2010, 02:26, insgesamt 1-mal geändert.

Benutzeravatar
theo
Beiträge: 10922
Registriert: Mo 11. Sep 2006, 19:01

Re: Initialisierung von Records

Beitrag von theo »

Naja, ist ja nur ein Hint. Also kann man den einfach ignorieren, wenn man weiss was man tut.

Wenn er dich stört, kannst du das machen, dann hält er die Klappe:

Code: Alles auswählen

procedure ZeroMemory(Destination: Pointer; Length: SizeInt);
begin
  FillChar(Destination^, Length, 0);
end;
 
procedure TForm1.Button1Click(Sender:TObject);
var Bla: TBla;
begin
  ZeroMemory(@Bla,SizeOf(Bla));
end;

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Initialisierung von Records

Beitrag von carli »

Mich stören auch die unnötigen Hints a la "parameter bla not used" - zumal ich bloß Callbacks implementiere, von denen nicht alle Parameter genutzt werden.

Lösung:

Code: Alles auswählen

{$HINTS OFF}
(* Hier mein Code, von dem ich weiß, was er macht *)
{$HINTS ON}

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: Initialisierung von Records

Beitrag von Hitman »

Warum schaltest du diese Hints dann nicht einfach "global" ab? Dann kannst du wenigstens gezielt sagen, welche Hints du magst und welche nicht, anstatt einfach alle zu killen.

Benutzeravatar
theo
Beiträge: 10922
Registriert: Mo 11. Sep 2006, 19:01

Re: Initialisierung von Records

Beitrag von theo »

Naja, ist auch ein bisschen Psycho mit diesen Hints.
Ich bin zufrieden, wenn ich nur noch ein paar Hints habe, und weiss, dass das OK geht.
Sogar Warnungen sind manchmal OK.
Warum ich die abschalten oder "wegprogrammieren" sollte, wüsste ich nicht.

joe
Beiträge: 37
Registriert: Fr 28. Mai 2010, 15:47

Re: Initialisierung von Records

Beitrag von joe »

Ja, die Sache mit den Hints und Warnings.
Grundsätzlich finde ich es ja toll, wenn der Compiler mich auf potentielle Schwachstellen in meinem Code hinweist.
Dann kann ich mir die Stellen ansehen und wenn ich nach nochmaligem draufgucken sicher bin, dass der Code so ok ist, dann würde ich dem Compiler das auch gerne mitteilen, sodass er mich mit diesen Stellen künftig nicht mehr nervt.
Im Falle der unused Parameter habe ich mittlerweile auch den entsprechenden Hint ausgeschaltet. Schöner wäre, wenn man das an jeden Parameter einzeln dran schreiben könnte, z.B.:

Code: Alles auswählen

procedure Button1Click(unused Sender: TObject);
  begin
  // ...
  end;
Der GCC kann sowas, obgleich das da IMHO nicht sonderlich schön lesbar ist:

Code: Alles auswählen

void Button1Click(__attribute__((unused)) TObject* Sender)
{
    // ...
}
I.d.R. definiere ich mir in C/C++ dafür ein Macro damit der Code wieder schöner lesbar und auch portabel wird:

Code: Alles auswählen

#define _UNUSED_   __attribute__((unused))
void Button1Click(_UNUSED_ TObject* Sender)
{
    // ...
}
Aber ok, zurück zu Pascal.

Meine Prämisse ist, der Code soll absolut ohne Hints und Warnungen kompilierbar sein.
So brauche ich beim Kompilieren nicht jedesmal nachsehen und feststellen: "Ach ja, dass sind ja die 17 Meldungen die ok sind" (mit der Gefahr dass ich dabei doch mal eine Wichtige Meldung übersehe).

Benutzeravatar
theo
Beiträge: 10922
Registriert: Mo 11. Sep 2006, 19:01

Re: Initialisierung von Records

Beitrag von theo »

joe hat geschrieben: Meine Prämisse ist, der Code soll absolut ohne Hints und Warnungen kompilierbar sein.
So brauche ich beim Kompilieren nicht jedesmal nachsehen und feststellen: "Ach ja, dass sind ja die 17 Meldungen die ok sind" (mit der Gefahr dass ich dabei doch mal eine Wichtige Meldung übersehe).
Wie gesagt: Psycho. ;-)

joe
Beiträge: 37
Registriert: Fr 28. Mai 2010, 15:47

Re: Initialisierung von Records

Beitrag von joe »

Ok, dann werd' ich mir wohl selbst ein SetZero() schreiben

Code: Alles auswählen

procedure SetZero(out x; count: SizeInt);
  begin
  {$HINTS OFF}
  FillByte(x,count,0);
  {$HINTS ON}
  end;
Und wenn ich merke, dass mir das wegen den automated types auf die Füsse fällt, dann schwenke ich eben um zu der Variante mit dem 1. Parameter als Pointer.

Socke
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: Initialisierung von Records [gelöst]

Beitrag von Socke »

joe hat geschrieben:Und wenn ich merke, dass mir das wegen den automated types auf die Füsse fällt, dann schwenke ich eben um zu der Variante mit dem 1. Parameter als Pointer.
Ich empfehle theos Variante. Da musst du zwar einen Pointer übergeben; dafür sollte das uneingeschränkt mit allen Typen funktionieren.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Initialisierung von Records [gelöst]

Beitrag von carli »

Naja über Hints, Warnings etc. kann man sich streiten (tu ich auch :D)

Mein Standpunkt ist, dass der Compiler so streng sein soll. Das verhindert Fehler. Sollte ich es aber absichtlich so wollen, muss es immer Wege geben (Typecasts, Hints off), die es mir ermöglichen, dem Compiler zu sagen, dass ich das genau so meine, wie es da steht. (egal wieviel Aufwand ich dann schreiben muss)

lrlr
Beiträge: 127
Registriert: Di 3. Nov 2009, 09:48

Re: Initialisierung von Records [gelöst]

Beitrag von lrlr »

>Wie gesagt: Psycho. ;-)

nein, das ist nicht psycho, ..

ich hab bis jetzt ja nur hobby projekte in lazarus,.. mit maximal 30 bis 40 (eigenen) units..

und da hab ich schon mehrere hints (wegen nicht verwendetet parameter usw.)

für die Arbeit wäre das undenkbar, wenn man dann auch noch (z.b. opensource) Komponenten anderer hätte, die sich auch nicht um diese hints kümmern, hast du SEITENWEISE hints

ich wüsste nicht warum man den aktuellen status "schön reden" sollten, das gehört einfach gelöst...

Benutzeravatar
theo
Beiträge: 10922
Registriert: Mo 11. Sep 2006, 19:01

Re: Initialisierung von Records [gelöst]

Beitrag von theo »

lrlr hat geschrieben:>Wie gesagt: Psycho. ;-)
nein, das ist nicht psycho, ..
Doch.
lrlr hat geschrieben: und da hab ich schon mehrere hints (wegen nicht verwendetet parameter usw.)
Hints ausschalten. Wenn die standardmässig aus wären, würden sie dich dann auch stören?

lrlr hat geschrieben: wenn man dann auch noch (z.b. opensource) Komponenten anderer hätte, die sich auch nicht um diese hints kümmern, hast du SEITENWEISE hints
Die siehst du üblicherweise nur beim installieren eines package, nachher nicht mehr.

lrlr
Beiträge: 127
Registriert: Di 3. Nov 2009, 09:48

Re: Initialisierung von Records [gelöst]

Beitrag von lrlr »

>Hints ausschalten.

nein, der Hint ist ja SEHR PRAKTISCH, ich will ihn nicht generell ausschalten,

ja, wenn es den hint nicht geben würde, würde ich ihn mir wünschen...

Benutzeravatar
theo
Beiträge: 10922
Registriert: Mo 11. Sep 2006, 19:01

Re: Initialisierung von Records [gelöst]

Beitrag von theo »

lrlr hat geschrieben: nein, der Hint ist ja SEHR PRAKTISCH, ich will ihn nicht generell ausschalten,
Was ist den daran praktisch? Ist doch meist nur ein Compiler Gemeckere ohne echte Auswirkungen.
Warnungen sind praktisch, aber selbst diese kann man oft stehen lassen, wenn man sich im Klaren ist, was man tut.

Zeit und Code dafür aufzuwenden, den Compiler ruhig zu stellen halte ich - wie gesagt - für psycho.

Socke
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: Initialisierung von Records [gelöst]

Beitrag von Socke »

theo hat geschrieben:Was ist den daran praktisch? Ist doch meist nur ein Compiler Gemeckere ohne echte Auswirkungen.
Warnungen sind praktisch, aber selbst diese kann man oft stehen lassen, wenn man sich im Klaren ist, was man tut.
Das erinnert mich an SQLite. Auf deren Webseite heißt es sinngemäß: Egal was der Compiler ausspuckt - sowohl an Warnungen/Hinweisen/etc. und an Binärem Output - wir testen das noch ausgiebig mit einem Testprogramm und wenn da alles klappt, ist’s in Ordnung. :D
Meiner Meinung nach entspricht das eher C als Pascal. Pascal wurde als Lehrsprache entworfen um auch das saubere Programmieren zu lehren. Dazu gehört (nicht nur) für mich, dass der Compiler meckert, sobald etwas nicht richtig (gemäß der Sprache) umgesetzt ist.
Bei einem Hinweis, kann man sich darüber streiten, ob der Compiler zu vorsichtig und der Programmierer allwissend bzgl. seines Codes ist oder der Programmierer auf die Sicherheit des Compilers vertrauen sollte.
Andererseits ist der Compiler nicht die absolute Instanz, die dich davor bewahrt, unmögliches anzustellen. Man kann problemlos eine Methode (d.h. Funktion eines Objektes) als ganz normale Funktion aufrufen und es gibt keine Compiler-Warnung.

Ich bin für sauber programmierten Code! Auch wenn Lazarus ein paar mehr Filtermöglichkeiten für die Compiler-Ausgabe besitzen sollte (genau das, was bei dem nicht genutzten Parameter "Sender" passiert). Ich gebe auch zu, die LCL und andere Pakete einfach zu kompilieren ohne alle Meldungen zu beseitigen :oops: (und schäme mich nicht dafür).
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten