Newsgroup: it.comp.lang.delphi
Titolo: free di oggetti a visibilita' locale

salve a tutti
in una procedura ho la seguente dichiarazione:
   LineaSolaio: array[1..10] of TLinea;
poi creo le istanze degli oggetti
   for i := 1 to Nv do
     LineaSolaio[i] := TLinea.create;
e infine li distruggo
   for i := 1 to Nv do
     LineaSolaio[i].Free;
mi sembrava la cosa corretta e invece mi da' errore
tutto funziona bene se non uso Free! perche'?
-- 
Using Opera's revolutionary e-mail client: 
http://www.opera.com/mail/

Se vedo bene con Nv non istanzi tutti i 10 oggetti dell'array: sei sicuro 
che quando fai il free il ciclo non arrivi ad una posizione cui non 
corrisponde nulla?
Nel ciclo del free, prova con
If Assigned( LineaSolaio[ i ] ) then
    begin
    LineaSolaio[i].Free;
    LineaSolaio[i] := nil; // importante se riutilizzi l'array
    end;
Se cosě funziona, significa che controlli malamente la variabile Nv che nel 
free assume un valore piů ampio degli oggetti realmente istanziati.
Ciao

 tutto funziona bene se non uso Free! perche'?
Perché le variabili locali di una funzione/procedura non sono
inizializzate come solitamente accade per quelle globali e membri di
classe.  
Se non istanzi tutti e 10 gli elementi ma solo N<10, come è presumibile
che tu faccia, i restanti 10-N non contengono indirizzi di memoria validi,
ma valori casuali, quindi una Free potrebbe generare un Access Violation
(n.b.: "potrebbe", perché non è mica detto che lo faccia).
Assicurati, quindi, all'inizio della procedura, di inizializzare gli
elementi:
for I := Low(Linee) to High(Linee) do
  Linee[I] := nil;
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 If Assigned( LineaSolaio[ i ] ) then
Non va bene.  Gli elementi di LineaSolaio non vengono inizializzati e
comunque non serve controllare che un puntatore sia <> nil prima di fare
la Free.
Infine, l'impostazione a nil non serve assolutamente a nulla e
sinceramente non mi sembra neanche importante ai fini del riutilizzo
dell'array.



Mi è capitato di metter mano a codici in cui si usano vettori a dimensione
fissa, ma il numero di elementi istanziati realmente è dinamico (una specie
di stack), oppure ogni singolo elemento può o no essere istanziato (una
sorta di vettore "booleano" in cui ogni elemento ha un suo significato e,
istante per istante, ci può essere o meno). In pratica, una data posizione
dell'array può essere usata, liberata, e riutilizzata in seguito. Per sapere
se una posizione è valida o deve essere rigenerata, dopo il free devo
rimettere a nil il puntatore, così come tu hai giustamente spiegato che si
deve fare la prima volta.
Tutto questo ovviamente pensando che l'array non sia locale ad un metodo....
dettaglio che avevo sorvolato nel leggere il post di cicogna (pardon).
Gianni

 Giusto? Questo errore potrebbe non avere conseguenze
Uno sforamento di un array ed un *eventuale* Access Violation ha sempre
conseguenze...


grazie a tutti per i suggerimenti ma
ho modificato il codice come segue:
   for i := Low(LineaSolaio) to High(LineaSolaio) do
     LineaSolaio[i] := nil;		(questa e' comunque pleonastica)
   for i := Low(LineaSolaio) to High(LineaSolaio) do
     LineaSolaio[i] := TLinea.create;
............
   for i := Low(LineaSolaio) to High(LineaSolaio) do
     LineaSolaio[i].Free;
e da' sempre Access violation con l'indice i=1 (primo elemento dell'array)
????? allora che faccio, se non distruggo gli oggetti la memoria non si  
gonfia fino a scoppiare?
e poi perche' diavolo deve dare errore????

 gonfia fino a scoppiare?
Mi sa di si! Fare finta di niente e non distruggere gli oggetti non e' 
mai la soluzione giusta! :)
ciao
Giacomo

dare errore anche senza l'array, con una semplica variabile.
Non è detto.  Gli AV possono anche non venire fuori, nonostante
persistano "sforamenti" di qualunque tipo.

e poi perche' diavolo deve dare errore????
Controlla il codice del costruttore/distruttore di TLinea. 

 Controlla il codice del costruttore/distruttore di TLinea.
constructor TLinea.create;
begin
   NPoints := 2;
end;
non c'e nessun codice per il distruttore
ecco la classe:
   TLinea = class
   public
     P: array[1..6] of TPunto;
     NPoints: integer;
     function Alfa: double;
     //angolo in radianti misurato in senso antiorario guardando da P1 a P2
     function Length: double;
     function MinX: double;
     function MaxX: double;
     function MinY: double;
     function MaxY: double;
     function XG: double;
     function PMedio: TPunto;
     procedure Assign(linea: TLinea);
     procedure Draw;
     constructor create;
   end;


 non c'e nessun codice per il distruttore
OK, allora il problema non e' qui ma nel codice che crea e distrugge gli 
array.
Bisogna che vediamo il codice effettivo della procedura. Semplificala
il piu' possibile e postala qui.
ciao
Giacomo

ecco la procedura:
procedure TCampoSolaio.FindDirezione(h: double);
//cerca la direzione più probabile del solaio per una spezzata
var
   i, k, nScelta: integer;
   ProbScelta: double;
   PP: TPunto;
   P2trans, PMtrans, PPtrans: TPunto;
   prob: array[1..10] of double; //probabilità di essere la direzione giusta
   PLD: array[1..10] of TLinea;  //possibile linea di direzione
   AlmenoUnaLineaParallela: boolean;
   dst, aff: double;
begin
   for i := Low(PLD) to High(PLD) do
     PLD[i] := nil;
   for i := Low(PLD) to High(PLD) do
     PLD[i] := TLinea.create;
   FindMinMaxXY;
   for i := 1 to nv do
   begin
     k := iVSucc(i);
     //trova la perpendicolare al lato passante per il punto medio
     SetTrns(V[i], V[k]);
     P2trans := Trns(V[k]);
     PMtrans := Trns(PMedio);
     PPtrans.x := PMtrans.x;
     PPtrans.y := 0;
     PP := TrnsInv(PPtrans);
     //trova le intersezioni della perpendicolare col poligono
     PLD[i] := Intersezioni(PMedio, PP);
     prob[i] := pds(PLD[i].Length, h);
   end;
   //probabilità nulla se la linea non è nè parallela nè perpendicolare
   //ad almeno un'altra linea
   if nv > 3 then
   begin
     for i := 1 to nv do
     begin
       AlmenoUnaLineaParallela := false;
       for k := i to nv do
       begin
         if k <> i then
         begin
           if LineeParallele(V[i], V[iVSucc(i)], V[k], V[iVSucc(k)], dst,  
aff) then
             AlmenoUnaLineaParallela := true;
         end;
       end;
       if not AlmenoUnaLineaParallela then
         prob[i] := 0;
     end;
   end;
   nScelta := 1;
   ProbScelta := 0;
   for i := 1 to nv do
   begin
     if ProbScelta < prob[i] then
     begin
       ProbScelta := prob[i];
       nScelta := i;
     end;
   end;
   DirezioneSolaio.Assign(PLD[nScelta]);
   for i := Low(PLD) to High(PLD) do
   begin
     PLD[i].Free;     //qui da' Access Violation
   end;
end;


 wrote:


    Result := TLinea.Create;   <--- questa e' necessaria?
Ovvio.
