Newsgroup: it.comp.lang.delphi
Titolo: Distruzione di oggetti VCL

Ciao a tutti, rileggendo vecchi post nel gruppo, mi sono venuti in mente
alcuni dubbi che cercherò di eliminare con il vostro aiuto, ma date una
occhiata a questo frammento di codice...
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  action := caFree; // libero l'istanza
  Form2 := nil; // ri-inizializzo il puntatore
end;
Ora a me le operazioni che si eseguono sopra non mi sembrano molto
corrette, in quanto pongo a nil Form2 prima che esso (il puntatore)
venga rilasciato, di conseguenza quando viene chiamata la delete
(scusatemi faccio riferimento al C++ in quanto  non conosco la sintassi
di delphi) il puntatore non punta + all' indirizzo iniziale, ma a nil...
Ora però provate a leggere il commento di chi ha scritto il codice
incriminato...
"Il fatto è che sebbene non ne sia sicurissimo, mi sembra di ricordare
che il
parametro action che tu imposti non determina l'immediata distruzione
della
Form (quindi effettivamente io imposto il puntatore Form2 a nil prima di
che
questa venga fisicamente distrutta). Il fatto è che una volta impostata
action a caFree la form viene distrutta dall'interno ( = non viene +
sfruttato il puntatore Form2 che è una variabile ( puntatore )_esterna_
... ) Ripeto: non sono proprio sicurissimo che funzioni così ma so _per
certo_ che
il mio procedimento è sicuro da un punto di vista della liberazione
della
memoria. "
Da qui nascono i miei dubbi... sarà vero ? A voi risulta qualcosa in
merito ? Io no sono riuscito a trovare una risposta, una cosa è certa,
Form2 viene posta a nil prima della chiamata di delete, è possibile però
che all' interno del codice VCL i programmatori Borland abbiano fatto
una copia dell' indirizzo di memoria da liberare e lo facciano tramite
questo... bhooo...
Ancora una domanda, per quanto riguarda gli oggetti TThead, esite un
modo per settare a nil un puntatore rilasciato automaticamente settando
FreeOnTerminate=true; nel momento in cui il thread stesso termini ?
Ciao a tutti e grazie per l' attenzione !
Bye Dave.

FreeOnTerminate=true; nel momento in cui il thread stesso termini ?
No ed è giusto così.  Non sarebbe una logica corretta da parte del
sistema.  Se n'è già parlato.

 FreeOnTerminate=true; nel momento in cui il thread stesso termini ?
In questo caso non ho ben capito cosa intendi.
Ciao

bisogno che la variabile "Form2" contenga l'indirizzo corretto 
Certo che ne ha bisogno, invece.

 occhiata a questo frammento di codice...
Vi ringrazio innanzitutto per le risposte, anche se ora ho le idee confuse
come prima, qualcuno dice si, qaulcuno dice no...  ;-) intanto mi sono fatto
un giro sul news dedicato alle VCL e ho riscontrato che effettivamente
parecchi consigliano di fare in questo modo...
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  action := caFree; // libero l'istanza
  Form2 := nil; // ri-inizializzo il puntatore
end;
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
  Action=caFree;
  Form2=NULL;
}
rispettivamente per Delphi e BCB..., mi rimane comunquel il dubbio... il
consiglio di andare a vedere il codice delle VCL è ottimo peccato che sia
scritto in Delphi prendo comunque per valida la spiegazione di Maurizio...
Grazie Ancora Dave.

 Certo che ne ha bisogno, invece.
No invece, inoltre fai questa prova:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   action := caFree; // libero l'istanza
   // Form2 esiste ancora eccome!!!
   ShowMessage(Form2.Name);
   // puoi fare anche così se preferisci (io lo preferisco)
   ShowMessage(Self.Name);
end;
Per la cronaca scrivere:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   action := caFree; // libero l'istanza
   Form2 := nil; // ri-inizializzo il puntatore
end;
è corretto anche se brutto (perchè come abbiamo detto si utilizza la var 
"Form2") lo scrive Marco Cantù in Mastering D2005 a pag. 279, ed io di 
quello che dice Marco mi fido cecamente.
Ciao

 Ciao
Mi spiego meglio, ho un Thread con FreeOnTerminate=true, in questo thread gira
un semplice cilclo che mi esegue solo 100 iterazioni, al termine del ciclo il
puntatore al mio Thread viene rilasciato automaticamente grazie a
FreeOnTerminate=true, quello che intendevo sapere è se esisteva qualche metodo
per fare in modo che il mio puntatore oltre che ad essere reso free venga anche
impostato a nil in maniera automatica, in modo ad esempio di verificare se il
Thread è stato effettivamente liberato prima di riallocarlo..., ma a questa
domanda ha già risposto Andrea e mi sembrava piuttosto deciso e convinto ;-)
Ciao e Grazie ancora a tutti e 2
Bye Dave.

 end; 
inserendo il commento "libero l'istanza" (che non è presente sul libro a 
cui fai riferimento) riferito ad un'istruzione che di fatto non libera 
alcunché, ma imposta semplicemente un parametro.
Non mi stupisce, quindi, che le due successive istruzioni vadano a buon 
fine e che l'istanza esista ancora: hai maleinterpretato il significato 
dell'impostazione del parametro /Action/.
Ad ogni modo, di questo argomento abbiamo parlato proprio recentemente.
L'impostazione del parametro /Action/, al ritorno dal metodo di gestione 
dell'evento, provoca l'esecuzione del metodo /Release/ che inserisce un 
messaggio in cima al thread dell'applicazione il quale si occuperà di 
distruggere il form.
Se esiste una sola istanza del form, è possibile impostare a *nil* la 
variabile fornita da Delphi, comoda ed efficace (per chi conosce i 
risvolti e le conseguenze del suo uso e il suo ruolo) ma sempre 
fuorviante per chi la sfrutta poi in modi che fanno "a cazzotti" con il 
rispetto della programmazione OOP; se esistono più istanze del form, è 
letteralmente impossibile fare riferimento a tale variabile; in 
generale, comunque, è sempre meglio evitarne l'uso all'interno dei 
metodi della classe del form, anche nel caso della chiusura, pena 
effetti indesiderati se il progetto si complica un attimo e aumentano i 
rapporti tra quel form e gli altri moduli di cui il progetto è composto.
Pur riportando l'esempio di cui sopra - ma senza i commenti aggiunti nel 
modo errato - questo è quanto viene detto anche nel libro di Cantù.
In sostanza, non c'è alcuna intenzione di voler far credere che la 
variabile creata da Delphi e utilizzata in quel modo sia l'unica e la 
più consigliabile delle soluzioni.
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)

"Form2") 
Non ha senso parlare di correttezza.  Il metodo che proponi č
sbagliato a prescindere, proprio perché utilizzi una variabile
specifica.

[...]prendo comunque per valida la spiegazione di Maurizio...
E fai male.

Rispondo una sola volta anche per Marco Breveglieri.
Faccio il punto su quello che ho detto dato che altrimenti si finisce 
nell'equivoco.
Se quello che vado a ribadire adesso non è quello che HO già scritto 
ditemelo...
L'esempio postato da DAVE inizialmente è il seguente:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   action := caFree; // libero l'istanza
   Form2 := nil; // ri-inizializzo il puntatore
end;
in merito a questo esempio (ed oviamente alle domande poste da Dave) ho 
scritto:
Il settaggio della variabile "Action" non fa niente se non settare una 
variabile passata per riferimento, nella TCustom.Form.Close verrà 
chiamata la "Release" se la variabile è = caFree !
La tecnica di utilizzare "Form2" è da sconsigliare, ho inoltre postato 
un pezzo di codice che fa un esempio del perchè.
Ho scritto a chiare lettere che io non lo faccio, preferisco impostare a 
nil in altro questi puntatori.
Per Marco B.:
Ho citato una pagina di MD2005 ma non ho riportato l'esempio di questo 
libro !
Il pezzo di codice è quello di Dave!
E' per questo che il commento è quello!
Non ho male interpretato il libro, scusa se te lo dico ma dovevi leggere 
i miei post precedenti prima di rispondere.
Non solo dico che la Release viene fatta dopo ma dico anche dove 
esattamente.
Dico anche che questo sistema non va bene se si vuole usare più form di 
quella classe, avevo addirittura fatto un esempio proprio per questo!
A questo punto vogliamo ridare a Cesare quello che è di Cesare, senza 
bisticci o prese di posizioni da parte di nessuno.
A me piacciono i confronti e non gli scontri (questo non è per Marco B.)
Su questo particolare aspetto sono informato e sono in grado di 
dimostrare con gli esempi di codice (che sottolineo avevo già fornito) 
che quanto affermo è giusto.
A questo punto chiedo ad Andrea L., che dai suoi post mi è sempre 
sembrata una persona con una buon bagaglio di conoscenze, un giduzio 
obiettivo e sereno.
Se siamo qui a postare è per scambiarci idee e consigli e non per far 
prevalere le prorpie ragioni, non so a voi ma a me non mi paga nessuno 
se leggo e posto ogni tanto e per piacere.
Un saluto a tutti.
Maurizio

 
Adesso ho capito, ho usato poche volte i Thread ma in ogni caso non mi 
ero mai posto il problema di un impostazione automatica del puntatore a nil.
Quando mi è capitato di usarli mi ricordo di aver memorizzato l'esito 
dell'esecuzione del Thread in una variabile che veniva passata per 
riferimento al Thread (se poi sei interessato ti spiego meglio come).
Questo mi permetteva di sapere se il Thread era finito, cosa c'entra con 
mettere a nil il puntatore?
Testando la variabile sapevo se il lavoro era terminato e quindi il 
Thread disallocato, se non ho capito male il tuo problema è quello di 
essere sicuro di non usare puntatori che non puntano a nulla!
Ciao

 i miei post precedenti prima di rispondere.
Li ho letti, ma mi ero perso nei meandri della spiegazione...
Ho riletto e ho compreso.
Probabilmente stiamo intendendo la stessa cosa ma non me n'ero 
accorto... :-)


libro !
E hai detto di fidarti ciecamente della tecnica *SBAGLIATA* che in
quel libro viene descritta.
Ora, per cortesia, fammi il piacere di tacere sull'argomento, per non
trasferire nozioni *ERRATE* a chi legge i tuoi messaggi.

 
Stiamo intendendo proprio la stessa cosa, ero sicuro che sarei riuscito 
a chiarire.
Ciao e grazie
Maurizio

 trasferire nozioni *ERRATE* a chi legge i tuoi messaggi.
Dovrei farti il piacere di tacere?
Ma non ti sembra di comportarti male?
Questo è un NG, lo spirito che lo anima non deve essere questo.
Forse dovrei evitare di proseguire questa discussione sta diventando un 
bisticcio ridicolo.
Ciao
Maurizio

bisticcio ridicolo.
Questa discussione è, come molte altre discussioni, ridicola perché
c'è qualcuno, come te, che si ostina a non voler capire qual è il modo
corretto di programmare in Delphi e si ostina a presentare la propria
soluzione come valida, ancorché gli sia stato dimostrato più e più
volte che è sbagliata.

volte che č sbagliata.
Rileggi tu il mio *primo* post e dimostra che č sbagliato se ci riesci
(magari fallo con calma cosě lo capisci meglio), altrimenti evita di
tergiversare.
Se mi risponderai civilmente e parlando di Delphi ti risponderň con
altrettanta educazione, diversamente continua pure ad inveire... ma da
solo.

 Ciao
Fondamentalmente si, ma era piuttosto una curiosità di sapere se esisteva un metodo
alternativo semplice e veloce, in quanto anche io per sapere se il lavoro del thread
era terminato ho sempre utilizzato una soluzione simile alla tua..., per quanto
riguarda l' altro quesito, ho fatto 2 prove empiriche, ed effettivamente la memoria
allocata da Form2 viene rilasciata anche se si fa perdere il riferimento allo stesso
dall' interno dell' evento OnClose... giusta o meno che sia la tecnica utilizzata il
risultato è comunque quello...
Vi rigrazio di avermi dedicato il vostro tempo...
Salutoni a tutti Dave.

Salutoni a tutti Dave.
Ciao
Maurizio