Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: AndreaM - Luglio 28, 2013, 03:39:27 pm

Titolo: Gestione Memoria degli Oggetti
Inserito da: AndreaM - Luglio 28, 2013, 03:39:27 pm
Salve a tutti!
Ho creato un mio oggetto per esempio TCane così definito in una Unit separata.
Codice: [Seleziona]
TCane = class(TObject) // Classe di prova
  private
    FNome:string;
  public
    Constructor Create(Nome:String);
    destructor Destroy; override;
    Property Nome:string read Fnome write Fnome;
  end; 
constructor TCane.Create(Nome:String);
begin
  inherited Create;
  FNome:=Nome;
end;
destructor Tcane.Destroy;
begin
  inherited Destroy;
end;
Questa classe è banale, ma solo per capire! Ora in una form figlia della applicazione uso il mio oggetto:
 
Codice: [Seleziona]
public
    Cane:TCane;
...
Se verifico cane se è assegnato mi dice ovviamente che cane=nil
Se faccio questa operazione:
Codice: [Seleziona]
cane:=TCane.Create('Pippo');
Vado a verificare di nuovo e mi dice ovviamente che cane e diverso da nli (è stato assegnato).
Se poi faccio:
Codice: [Seleziona]
cane.Free;
E verifico di nuovo mi dice ancora che cane<>nil! Perchè? Non ho liberato memoria?
Se poi faccio nuovamente:
Codice: [Seleziona]
cane.Free;
Il programma mi da errore, mentre se lo faccio prima del Create non ci sono problemi! Perche questo comportamento, come viene gestita la memoria?
Se io distruggo la form (form figlie) dove viene usata l'istanza di TCane, la memoria allocata viene liberata al momento della chiusura della form figlia? Oppure solo al momento della chisura della applicazione?
Un salutone a tutti e buon fresco  :'(
Titolo: Re:Gestione Memoria degli Oggetti
Inserito da: Stilgar - Luglio 28, 2013, 05:02:34 pm

Se crei un'istanza di un oggetto e l'assegni ad una variabile, anche chiamando .free o .destroy non hai la riassegnazione a nil. Hai il vecchio putatore, che punta a fuffa in memoria.

Stilgar
Titolo: Re:Gestione Memoria degli Oggetti
Inserito da: AndreaM - Luglio 28, 2013, 05:18:03 pm
Citazione
... che punta a fuffa in memoria.
Che vuoi dire?

Poi vorrei capire un'altra cosa!
Se io ho una form che non viene autocreata da lazarus, ma la gestisco io a runtime con un codice tipo:
Codice: [Seleziona]
try
  Form2:=TForm2.Create(self); // creo la form
  form2.ShowModal; // mostra la form
finally
  Form2.Free;
end;     
Se dento questa form c'è un oggetto che ho istanziato e usato, dopo la chiamata a Form2.Free questo oggetto è ancora disponibile nella Form1?
Titolo: Re:Gestione Memoria degli Oggetti
Inserito da: Stilgar - Luglio 28, 2013, 05:34:57 pm
Ciao,
 hai un pochino di confusione in testa.
Allora vediamo di chiarire alcuni concetti base.
I puntatori in memoria sono dei numeri che vengono usati in modo "speciale".
Se allochi la memoria il numero che ne ottieni è l'indirizzo di memoria che puoi usare (le istanze degli oggetti sono dei puntatori a tutti gli effetti).
Quando deallochi la memoria, "liberi" questa e la rendi disponibile per altri usi.
Quando chiami il distruttore di un oggetto, non fai altro che deallocare memoria.
A questo punto la memoria che hai usato in precedenza continua a contenere i vecchi dati, ma nn prenderla come regola aurea, nessun compilatore da questa garanzia. Da qui il termine fuffa.
Quando gestisci tu le istanze di una form (la form2 del tuo esempio) le cose non cambiano.
Quindi se chiami un qualsiasi metodo dopo averlo deallocato, otterrai un errore in esecuzione.
Per alcuni meccanismi interni della struttura in memoria dell'oggetto (il codice compilato è condiviso, ma i dati dell'istanza dell'oggetto è separato) puoi anche entrare in debug nel metodo, ma poi hai errori a manetta. Se controlli Self come variabile vedrai che il debugger di dice che non è un valore valido.
Forse è questo che ti crea della confusione.
In ogni caso dopo aver deallocato un oggetto è formalmente errato accedere ai suoi metodi. Anzi ... non ha proprio senso ;)
Stilgar
Titolo: Re:Gestione Memoria degli Oggetti
Inserito da: AndreaM - Luglio 28, 2013, 05:46:31 pm
Ok Stilgar,
Mi hai fatto chiarezza! Evidentemente se punto alla memoria appena liberata il metodo riesce lo stesso a recuperare i dati, ma se nel frattempo il programma occupa la memoria liberata per altre cose e io riprovo con il mio metodo a recuperare i dati otterrei degli errori!
Un po come quando si cancellano file dall'HD, crei spazio disponibile ma un programma potrebbe recuperare i dati se quella partizione non viene sovrascritta!
Sei stato di grande aiuto!
Comincio a capire di più di questo mondo Pascal!  :)
Titolo: Re:Gestione Memoria degli Oggetti
Inserito da: Stilgar - Luglio 28, 2013, 08:53:42 pm
Di nulla.
Titolo: Re:Gestione Memoria degli Oggetti
Inserito da: AndreaM - Luglio 29, 2013, 09:37:39 am
Ora un'altro chiarimento quando si usa :=!
Se ad esempio in una form uso una sintassi di questo tipo:
Codice: [Seleziona]
Type 
  Primo,Secondo:TMyObject

E poi nel codice uso
Codice: [Seleziona]
Primo:=Secondo

Da quello che intuisco viene effettuato un reindirizzamento della memoria di secondo su primo!
E quindi posso utilizzare Primo al posto di secondo conservando tutti i metodi e le variabili interne a Secondo
Se è così posso poi fare
Codice: [Seleziona]
Secondo.free
E' lecito? Oppure se faccio
Codice: [Seleziona]
Primo.free
Elimino sia primo che secondo?
Grazie per i chiarimenti!
Andrea
Titolo: Re:Gestione Memoria degli Oggetti
Inserito da: Stilgar - Luglio 29, 2013, 01:48:34 pm
Ciao,
 hai 2 puntatori alla stessa cella di memoria.
Di conseguenza
Secondo.Free e Primo.Free sono sinonimi.
Liberi sempre la stessa area di memoria.

Stilgar