AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Objekt mit Free freigegeben, dennoch Zugriff auf Felder?
Thema durchsuchen
Ansicht
Themen-Optionen

Objekt mit Free freigegeben, dennoch Zugriff auf Felder?

Ein Thema von chaoslion · begonnen am 5. Sep 2010 · letzter Beitrag vom 5. Sep 2010
Antwort Antwort
chaoslion

Registriert seit: 1. Mär 2006
52 Beiträge
 
#1

Objekt mit Free freigegeben, dennoch Zugriff auf Felder?

  Alt 5. Sep 2010, 17:36
Delphi-Version: 2010
Hallo Leute,

folgende Klasse als Beispiel:
Delphi-Quellcode:
type blObject = class(TObject)
private
  _name: string;
public
  procedure _SetName( const s: string );
  function _GetName(): string;
end;
und dies zum Test:
Delphi-Quellcode:
  o := blObject.Create();
  o._SetName('test');
  o.Free();
  writeln(o._GetName())
Wie kann es sein dass, obwohl o freigegeben ist, Writeln auf _name zugreifen kann?
Sollte er hier nicht meckern, dass es o nicht mehr gibt bzw. auf ungültigen Speicher zeigt?
Er schreibt nichts, ausser der Leerzeile in die Konsole..

Beste Grüße!
  Mit Zitat antworten Zitat
Benutzerbild von igel457
igel457

Registriert seit: 31. Aug 2005
1.622 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Objekt mit Free freigegeben, dennoch Zugriff auf Felder?

  Alt 5. Sep 2010, 17:51
Der Aufruf von Free gibt lediglich den Speicher, den das Objekt belegt frei - das bedeutet, dass der vorher belegte Speicherbereich nun als erneut verwendbar markiert wird. Da Delphi eine eigene Speicherverwaltung besitzt wird dies u.U. nicht einmal dem Betriebsystem mitgeteilt: Der Objektzeiger "o" wird nicht verändert und die Daten des Objekts liegen immer noch im Speicher. Da du zwischen dem Free und dem Writeln keinen neuen Speicher reservierst, werden deine alten Objektdaten auch nicht überschrieben.

Sobald du neuen Speicher reservierst (dies kann auch durch Bibliotheksaufrufe, verändern der Größe eines Arrays etc.) besteht jedoch die Wahrscheinlichkeit, dass der Speicher des Objektes überschrieben wird und du mit jedem lesenden Zugriff auf das Objekt Müll ausliest und mit jedem schreibenden Zugriff beliebige andere Daten zerhackst, was zu sehr interessanten Fehlern führen kann.

Deshalb: Objekte frei geben und dann immer alle Objektzeiger darauf auf "nil" setzen. Versuchst du dann auf das Objekt zuzugreifen bekommst du eine aussagekräftige Fehlermeldung ("EAccessViolation while reading address 0x00000000"):
Delphi-Quellcode:
o.Free;
o := nil;
oder einfacher:
FreeAndNil(o);
Edit:
Im Falle von Methoden (wie in deinem Beispiel) ist die Sache noch ein wenig komplizierter. Intern sind alle (nicht virtuellen) Methoden einfache Funktionen, die einen versteckten, ersten Parameter "self" beinhalten, der den Wert des Objektzeigers hat. Folgendes ist also equivalent zu deinem Code:
Delphi-Quellcode:
type
  TblObject = record
    name: string;
  end;
  PblObject = ^TblObject;

function blObject_Create: PblObject;
begin
  new(result);
end;

procedure blObject_SetName(self: Pointer; name: string);
begin
  self^.name := name;
end;

function blObject_GetName(self: Pointer): string;
begin
  result := self^.name;
end;

procedure blObject_Free(self: Pointer);
begin
  Dispose(self);
end;

var
  o: PblObject;
begin
  o := blObject_Create();
  blObject_setName(o, 'name');
  blObject_free(o);
  writeln(blObject_getName(o));
end;
Die Methoden sind wie du siehst fest im Programmcode enthalten und sind nach Freigabe eines Objektes immer noch gültig. Solange eine nicht virtuelle Methode nicht auf Objektvariablen zugreift (also den versteckten "self" Parameter nicht verwendet), wird die Funktion immer ohne Fehlermeldung ausgeführt, selbst wenn "self" nil sein sollte. In deinem Fall trifft jedoch einfach das oben gesagte zu, nämlich dass die Freigabe den Speicher nur als "zur Wiederverwertung freigegeben" kennzeichnet, den Speicherinhalt jedoch nicht löscht.
Andreas
"Sollen sich auch alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen, und nicht mehr davon geistig erfasst haben als die Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst." - Albert Einstein

Geändert von igel457 ( 5. Sep 2010 um 18:02 Uhr)
  Mit Zitat antworten Zitat
chaoslion

Registriert seit: 1. Mär 2006
52 Beiträge
 
#3

AW: Objekt mit Free freigegeben, dennoch Zugriff auf Felder?

  Alt 5. Sep 2010, 17:54
Okay, sehr anschaulich erklärt, dank Dir!
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Objekt mit Free freigegeben, dennoch Zugriff auf Felder?

  Alt 5. Sep 2010, 17:58
Wegen DSL-Ausfall bin ich etwas spät, schicke es aber ergänzend trotzdem noch los...


Das "Objekt" ist eigegentlich ein Zeiger, der auf eine bestimmte Speicherstelle Zeigt, wo dann die Daten liegen.
Wird das Objekt freigegeben, kann der Speicher wieder vom Programm für andere Daten genutzt werden.

Du kannst Dein Objekt auf "nil" setzen.

Delphi-Quellcode:
o.Free;
o := nil;
oder

FreeAndNil(o), Dann kannst Du später prüfen, ob das Objekt existiert:

if o <> nil ... oder

if Assigned(o) ...
Nur mal noch zur Vervollständigung, Du kannst Dein Objekt auch so definieren und damit Eigenschaften mit Getter- und Setter-Methode verwenden:

Delphi-Quellcode:
blObject = class(TObject)
private
  F_Name: String;
protected
  procedure Set_Name(const Value: String);
  function Get_Name: String;
public
  property _Name: String read Get_Name write Set_Name;
end;
Dann kannst Du immer o._Name := 'xxx' und S := o._Name benutzen.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Antwort Antwort


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 19:40 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