AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi GetMem / FreeMem - New / Dispose
Thema durchsuchen
Ansicht
Themen-Optionen

GetMem / FreeMem - New / Dispose

Ein Thema von AJ_Oldendorf · begonnen am 8. Jun 2012 · letzter Beitrag vom 12. Jun 2012
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#11

AW: GetMem / FreeMem - New / Dispose

  Alt 8. Jun 2012, 13:05
Jetzt würde mich aber wirklich mal interessieren, was du mit unerklärlichen Fehlern meinst wenn man GetMem und FreeMem benutzt?
Nimm z.B. folgende Definition:
Delphi-Quellcode:
type
  MyRec = record
            f1 : Byte;
            f2 : Word;
            f3 : String[80]
 end;
Das sind 84 Byte Du arbeitest also mit Getmem(p,84);
Das Dumme ist nur, das ein mögliches Alignment nicht beachtet wurde. Und immer wenn der String 80..75 Zeichen lang wird, dann trittst Du irgend einer anderen Variablen auf die Füße.

Oder Du hast ein altes 16Bit-Programm und es wird in einer 32-Bit Umgebung neu erstellt. Dann ist ein Integer nicht mehr 16 sondern 32 Bit groß. Und zur Ermittlung des Speicherplatzes wird nicht Sizeof verwendet, sondern fest kodierte Werte. Das kann u.U. recht eklig werden.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector

Geändert von p80286 ( 8. Jun 2012 um 13:06 Uhr) Grund: Tippfehler
  Mit Zitat antworten Zitat
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#12

AW: GetMem / FreeMem - New / Dispose

  Alt 8. Jun 2012, 13:09
Er meint dass wie folgt:
Delphi-Quellcode:
type
  TRecord1 = record
    Wert1 : Integer;
  end;
  PRecord1 = ^TRecord1;//Pointer auf die Daten des TRecord1.

  TRecord2 = record
   Record1 : PRecord1; //Eine Variable vom PRecord1
  end;
  PRecord2 = ^TRecord2;

//Wenn du dies nun wie folgt initalisiertst:
var Record2 : PRecord2;
begin
  GetMem(Record2,SizeOf(TRecord2)); //Speicher vom Record-Typ, nicht vom Pointer-Typ :-D
  GetMem(Record2.Record1,SizeOf(TRecord1)); //Den TRecord1-Pointer in TRecord2 initalisieren.
  Record2.Record1.Wert1 := 10; //Als Test

  //Wenn du dies nun wie folgt freigibst nur...
  FreeMem(Record2,SizeOf(TRecord2)); //Zur Sicherheit würd ich die Größe nochmal übergeben.
  //...bleibt der Pointer auf TRecord1 in TRecord2 enthalten, also der Speicher von TRecord1 wird nicht freigegeben. Weil in TRecord1 nur der Pointer(Adresse, wo TRecord1 seine Daten hat), also nur der Adresswert, freigegeben wird.
  //In diesem Fall müsste mal folgendes machen:
  FreeMem(Record2.Record1,SizeOf(TRecord1));//Alle in diesem Pointer-Record-Typ enthaltenen Pointer musst du selbst freigeben. Bei Klassen halt Free davor aufrufen.
  FreeMem(Record2,SizeOf(TRecord2));//Danach erst den "Oben"-Pointer freigeben.
end;
Du musst halt sozusagen die hierarchie deines Pointers, wenn du es so machst wie in dem Beispiel, von unten nach oben freigeben, erst die untengeordneten, danach die oberen.
Auserdem macht GetMem nur Platz für die Daten. Es ist meist so, dass dort Werte von anderen freigegeben Speichern noch liegt. Weil GetMem halt nur sagt, so hier kannst deine Daten reinschreiben. Es gibt aber auch noch die AllocMem, mit der dann der Speicher mit "0"Bytes aufgefühlt wird, um solche Fehler zuvermeiden. Das kann dan auch mit FreeMem freigegen werden.
Dies ist genauso als würdest du GetMem und danach FillChar aufrufen.

EDIT: Habe gerade was getestet. Bei New/Dispose werden Pointer initalisiert, die nach Dispose noch verfügbar sind. D.h. der Speicher wird von Delphi freigegeben. Sozusagen wenn du wirklich Kontrolle über den Speicher für solche Pointer haben willst verwende lieber, GetMem/FreeMem. Bei falscher verwendung können halt solche genannten Fehler entstehen.

Hoffe ich konnte es dir erklären. Ist ein wenig kompliziert am anfang, ging mir auch so .
Aber einmal kapiert, sind Pointer und Speicher erstellen/freigeben ein kinderspiel xD
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.

Geändert von NickelM ( 8. Jun 2012 um 13:34 Uhr)
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
385 Beiträge
 
Delphi 12 Athens
 
#13

AW: GetMem / FreeMem - New / Dispose

  Alt 11. Jun 2012, 10:24
Zitat:
Nimm z.B. folgende Definition:
Delphi-Quellcode:
type
  MyRec = record
            f1 : Byte;
            f2 : Word;
            f3 : String[80]
 end;
Das sind 84 Byte Du arbeitest also mit Getmem(p,84);
Das Dumme ist nur, das ein mögliches Alignment nicht beachtet wurde. Und immer wenn der String 80..75 Zeichen lang wird, dann trittst Du irgend einer anderen Variablen auf die Füße.
Und wie sieht es aus, wenn ich mit packed records arbeite? Diese habe ich nämlich nur in Verwendung...
Wie meinst du das mit den "String 80..75 Zeichen", dass ich dann einer anderen Variablen auf die Füße trete?

Gruß
Alex
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#14

AW: GetMem / FreeMem - New / Dispose

  Alt 11. Jun 2012, 12:01
Und wie sieht es aus, wenn ich mit packed records arbeite? Diese habe ich nämlich nur in Verwendung...
Dann hast Du das Problem natürlich nicht.

Wie meinst du das mit den "String 80..75 Zeichen", dass ich dann einer anderen Variablen auf die Füße trete?
Du hast für die drei Variablen/Felder 84 Byte reserviert da sie nicht "packed" abgelegt werden beginnt der Datenbereich des Strings nicht beim 4. sondern beim 10. Byte.
Sobald der String länger als 74 Byte wird landen Zeichen im nicht zu Deinem Record gehörenden Speicher. Und das kann alles mögliche oder aber auch nichts sein. D.H. der Fehler wird unter Umständen erst auf einem anderen Rechner oder einem anderen Benutzer erkannt.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#15

AW: GetMem / FreeMem - New / Dispose

  Alt 11. Jun 2012, 12:02
Wie meinst du das mit den "String 80..75 Zeichen", dass ich dann einer anderen Variablen auf die Füße trete?
Wenn mit GetMem weniger Speicher reserviert wurde, als der Record groß ist, dann schreibst du auch schnell mal über das Ende des Records hinaus, wenn der String zu voll wird.

New und Dispose holen sich die "richtige" Größe aus der RTTI und führen auch noch eventuell notwendige Initialisierungen/Finalisierungen durch.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#16

AW: GetMem / FreeMem - New / Dispose

  Alt 12. Jun 2012, 13:40
Passt zum Thema
http://delphihaven.wordpress.com/201...pes-vs-getmem/
Markus Kinzler
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:45 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