31 Stimmen

Warum verwenden die meisten Delphi-Beispiele FillChar(), um Datensätze zu initialisieren?

Ich habe mich gerade gefragt, warum die meisten Delphi-Beispiele FillChar() zum Initialisieren von Datensätzen verwenden.

type
  TFoo = record
    i: Integer;
    s: string; // not safe in record, better use PChar instead
  end;

const
  EmptyFoo: TFoo = (i: 0; s: '');

procedure Test;
var
  Foo: TFoo;
  s2: string;
begin
  Foo := EmptyFoo; // initialize a record

  // Danger code starts
  FillChar(Foo, SizeOf(Foo), #0);
  s2 := Copy("Leak Test", 1, MaxInt); // The refcount of the string buffer = 1
  Foo.s = s2; // The refcount of s2 = 2
  FillChar(Foo, SizeOf(Foo), #0); // The refcount is expected to be 1, but it is still 2
end;
// After exiting the procedure, the string buffer still has 1 reference. This string buffer is regarded as a memory leak.

Hier ( http://stanleyxu2005.blogspot.com/2008/01/potential-memory-leak-by-initializing.html ) ist meine Anmerkung zu diesem Thema. IMO, deklarieren eine Konstante mit Standardwert ist ein besserer Weg.

2voto

skamradt Punkte 15128

Traditionell ist ein Zeichen ein einzelnes Byte (gilt nicht mehr für Delphi 2009), so dass die Verwendung von fillchar mit einer #0 den zugewiesenen Speicher so initialisieren würde, dass er nur Nullen oder Byte 0 oder bin 00000000 enthält.

Sie sollten stattdessen die ZeroMemory Funktion, die die gleichen Aufrufparameter wie die alte fillchar-Funktion hat.

1voto

Brian Frost Punkte 13154

Diese Frage hat eine umfassendere Bedeutung, die mir schon seit langem durch den Kopf geht. Auch ich bin mit der Verwendung von FillChar für Datensätze aufgewachsen. Das ist gut, denn wir fügen oft neue Felder zum (Daten-)Datensatz hinzu und natürlich kümmert sich FillChar( Rec, SizeOf( Rec), #0 ) um solche neuen Felder. Wenn wir es "richtig" machen, müssen wir alle Felder des Datensatzes durchgehen, von denen einige Aufzählungstypen sind und einige selbst Datensätze sein können, und der resultierende Code ist weniger lesbar und möglicherweise fehlerhaft, wenn wir nicht sorgfältig neue Datensatzfelder hinzufügen. String-Felder sind weit verbreitet, daher ist FillChar jetzt ein No-No. Vor ein paar Monaten, ging ich um und konvertierte alle meine FillChars auf Datensätze mit String-Feldern zu iterierten Clearing, aber ich war nicht glücklich mit der Lösung und frage mich, ob es eine saubere Art und Weise zu tun, die "Fill" auf einfach Typen (ordinal / float) und "Finalize" auf Varianten und Strings?

0voto

Server Overflow Punkte 19774

Hier ist ein besserer Weg, Dinge zu initialisieren, ohne FillChar zu verwenden:

Datensatz im Datensatz (kann nicht initialisiert werden)
Wie initialisiert man ein statisches Array?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X