Newsgroup: it.comp.lang.delphi
Titolo: Errore durante la chiusura di un form

Questa è difficile. Allora ho un form con un tasto che una volta premuto
non fa altro che chiamare l'evento Close. Qui sotto riporto il codice
dell'evento OnClose richiamato
procedure TFrmStatistiche.FormClose(Sender: TObject; var Action:
TCloseAction);
begin              
  FrmStatistiche := nil;
  Action := caFree;
end;
Come vedete è il massimo della semplicità. Ciononostante ho un bel
Access Violation che mi manda in crash il programma. Dopo una serie di
debug e/o test vari per capire l'origine del problema, l'ho individuato
nei puntatori a degli array di record che utilizzo nelle varie procedure
di calcolo del form. Tali oggetti sono così definiti:
type
  TOrario = record
    Ora: string;
    Totale: integer;
  end;
  TLavorativi = record
    Id       : string;
    Etichetta: string;
    Valore   : real;
  end;
  TStruttura = record
    Regione  : string;
    Etichetta: string;
    Sigla    : string;
    Aperte   : integer;
    Chiuse   : integer;
    ChiuseTmp: integer;
    Annullate: integer;
    Attesa   : integer;
    Prestito : integer;
    TotAperte: integer;
    TotChiuse: integer;
  end;
  TDettaglioChiusureGrafico = record
    Clo: integer;
    Cpc: integer;
  end;
  TTopProdotti = record
    Prodotto: string;
    Quantita: integer;
  end;
  ...
  private
    Data: array of TStruttura;
    Orario: array[0..23] of TOrario; // 00.00 -> 23.00
    Lavorativi: array of TLavorativi;
    DettaglioChiusureGrafico: array of DettaglioChiusureGrafico;       
    TopProdotti: array[0..14] of TTopProdotti;
Quello che mi sono immaginato è che per una qualche ragione quando vado
a chiudere il form questi oggetti (o magari i puntatori di questi) non
riescono ad essere distrutti in modo corretto. Ora il test che ho
provato a fare è stato impostare la Length degli array a 0 durante
l'onclose ma non ho avuto alcun miglioramento. Vorrei sottolineare che
un po' di tempo fa ho dovuto impostare la dimensione dell'array Orario
in modo statico poichè se la lasciavo dinamico mi dava un errore "out of
memory" durante l'elaborazione, a causa dei puntatori che per qualche
ragione perdevano il corretto puntamento (ad es. mi ritrovavo nella
posizione 4 una stringa contenente i valori di tutto l'intero array!!!)
Sicuramente sbaglio qualcosa, ma cosa?!?
Suggerimenti?
Un saluto, 
Dario
 
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

xche array e non liste?
xche record e non classi?
AS

 xche record e non classi?
xche da sempre utilizzo quel format! sbaglio? xchč?
ciao, 
dario


Non è che sbagli...
è solo che le classi permettono una migliore organizzazione del
codice.
Un array di tipi record, ad esempio, puo essere facilmente sostiuito da
una tlist o una tobjectlist che contiene istanze di classi.
Questo ti permette di sfruttare a pieno la potenza della OOP, cosa che
non i tipi record non fai..
AS
, a differenza delle classi, i tipi record in delphi non permettono
l'implementazione di metodi, non permettono il polimof

 wrote in message
news:1139236593....@z14g2000cwz.googlegroups.com
Ho convertito tutti i miei record in class ed ora tutto funziona. 
Grazie mille.
Però mi togli una curiosità: alla luce di tutto questo, a che servono i
tipi record? 
Dario


 tipi record?
1) Le api di windows, basata su linguaggio c, fanno largo uso delle
struct, che altro non sono che tipi record delphi/pascal
2) In alcuni casi le classi non puoi usarle, ad esempio:
var
  MyFile: File Of TSomeType;
3) retrocompatibilità
AS

tipi record? 
Derivano dal Pascal, che non era un linguaggio orientato agli oggetti.
Purtroppo il Pascal ha subito una evoluzione diversa, verso l'OOP,
rispetto a quanto accaduto, ad esempio, con il C++.  In C++, ad
esempio, non c'è _alcuna_ differenza tra le struct (equivalenti ai
record) e le class.  Sono esattamente la stessa cosa (tanto è vero che
anche le struct possono avere metodi), a meno dello specificatore di
visibilità di default (che per le struct è public e per le class è
private).  In Pascal, si sarebbe potuta fare la stessa cosa, far
evolvere i record, facendo spuntare loro le "ali".  Risultato è che
oggi record e class rimangono strutture profondamente diverse e molti
programmatori sono disorientati su cosa usare.  I record offrono il
vantaggio dell'allocazione statica (per cui non richiedono menate
Create/try...finally/Free), mentre le classi offrono altri vantaggi
per quanto riguarda l'incapsulamento dei comportamenti.

 
-- 
Ciao, Anto', [38, 143, AQ] 
MB C SC 220 CDI Magma Rot
"Oggi c'è una grande battaglia di idee, ma alla 
fine, non ci saranno ne vinti, ne vincitori, ne idee!"
S. Benni da Elianto

 toglimi una curiositŕ, hai provato ad invertire l'ordine delle istruzioni?
Sě. Ho provato molte sintassi tra le quali anche il FreeAndNil(Self) ma
senza riuscire a venirne a capo.


 toglimi una curiosità, hai provato ad invertire l'ordine delle istruzioni?
Mmm credo di no (onestamente non ricordo perchè ho pacioccato parecchio
nell'evento OnClose per cercare di venirne fuori). Dici che sarebbe
bastato?


 toglimi una curiosità, hai provato ad invertire l'ordine delle istruzioni?
Mmm credo di no (onestamente non ricordo perchè ho pacioccato parecchio
nell'evento OnClose per cercare di venirne fuori). Dici che sarebbe
bastato?


 leak.
Così però te le cerchi! Che cosa sono i memory leka?  :) 
Cmq non credo di aver fatto casotto: l'unità è abbastanza complessa a
livello di calcolo, credo che se ci fosse stato qualcosa che non andava
a quest'ora me ne sarei accorto.


 per quanto riguarda l'incapsulamento dei comportamenti.
Perň l'allocazione statica non č proprio quella che mi ha fregato?
Sembrava quasi che nello svolgimento del programma i puntatori se ne
andassero a spasso per fatti loro! Ho citato l'esempio del mio oggetto
Orario. Era una struttura semplicissima contenente le 24 ore:
Orario[0].Ora -> 00.00
Orario[1].Ora -> 01.00
Orario[2].Ora -> 02.00
Orario[3].Ora -> 03.00
eppure quando la mettevo in un ciclo for mi risultava ad esempio
Orario[4].Ora -> 00.00#13#1000.01#13#1002.00 etc etc  come
se avesse incapsulato nella posizione 4 tutto l'array.
Questo problema non si presentava sempre, solo ogni tanto: e dato che la
costruzione di questo array era piů che corretta (ne sono certo!) non
poteva che essere un problmea di puntatore che per qualche ragione si
perdeva in memoria. Vorrei evidenziare perň che io non utilizzavo i 
puntatori corretti (quelli con la sintassi ^puntatore per intenderci),
bensě una semplice variabile numerica. Che magari il problema non fosse
solo quello?


perdeva in memoria.
Il sistema difficilmente prende decisioni per conto suo, tantomeno
manda in giro a spasso i puntatori.  Quando ci sono problemi di questo
tipo (a meno di clamorosi, ma escludibili nel 99,99% dei casi, bug del
compilatore), si tratta di difetti di organizzazione del codice.

> Così però te le cerchi! Che cosa sono i memory leka?  :)
memory LEAK: risorsa allocata ma non liberata.
Ad esempio, crei una istanza, la usi ma alla fine non ne fai la free.
Ergo, se la tua app sfrutta quel pezzo di codice + volte, alle fine il
sistema fa boom.
Per garantirsi da queste eventualità si usa try..finally:
   qualcosa := TQualcosa.Create;
   try
       qualcosa.FaiQualcosa();
   finally
       qualcosa.free;
   end;
AS

Sicuramente sbaglio qualcosa, ma cosa?!?
Bisognerebbe guardare il codice che utilizza quelle variabili.
Difficile rispondere, altrimenti, senza sfera di cristallo.

 Difficile rispondere, altrimenti, senza sfera di cristallo.
Guarda ti riportio un pezzo di codice giusto per farti capire. Questo č
il ciclo in cui monto il mio array con gil orari:
  Ora := 0;
  for i:=0 to Length(Orario) -1 do begin
    Orario[i].Ora := FormatDateTime('hh.nn', Ora);
    Orario[i].Totale := 0;
    Ora := Ora + EncodeTime(1, 0, 0, 0);
  end;
Credo che questa sia una sintassi da considerarsi corretta (se no lo č
correggimi pure)
var Ora: integer
begin
while not ClientDataSet.Eof do begin
  Ora := StrToInt( Copy(ClientDataSet.Fields[0].AsString, 1, 2) );
  Inc(Orario[ora].Totale);
  ClientDataSet.Next;
end;
Il campo [0] di ClientDataSet contiene delle stringhe con degli orari
(es. 15.34): io prendo i primi due chr e li converto in numero cosě da
ottenere la posizione corretta nell'array. I primi 3-4 record me li
processa bene, poi inizia il "patatrack" dopra descritto: debuggando,
Orario[i].Ora vale una stringa pazzesca 00.00#10#1300.02#etc etc...
Come succeda non l'ho ancora capito :(


  Inc(Orario[ora].Totale);
...e vedrai che un bel "ciao!" verrà fuori, prima o poi...

   Action := caFree;
IMHO qualcosa non quadra!!!


 IMHO qualcosa non quadra!!!
Forse hai ragione tu. Proverň in un secondo momento e posterň il 
risultato. Grazie per il suggerimento.


 ...e vedrai che un bel "ciao!" verrà fuori, prima o poi...
So a cosa miri ma ti posso garantire che i record processati hanno tutti
i valori corretti poichè c'è un controllo precedente sulla loro 
immissione. Quindi è impossibile che uno abbia inserito un orario che
non sia corretto (tra l'altro l'ho anche potuto verificare direttamente
dalla tabella). Magari come hai detto tu sono capitato in quell'1% di 
probabilità in cui il compilatore ha fatto cilecca. Ultimamente ho 
parecchi problemi con il Delphi: non mi legge i punti di debug, mi
segnala
crash sui package... insomma qualcosa di anomalo c'è!


probabilità in cui il compilatore ha fatto cilecca. 
Lo escludo.  Controlla il codice e vedrai che c'è qualcosa di
sbagliato.

toglimi una curiositŕ, hai provato ad invertire l'ordine delle istruzioni?
Non avevo notato quel codice.  Temo proprio che il problema sia lě.
Ribadisco che č una pessima abitudine quella di usare il nome
dell'istanza creato da Delphi per default, nel codice generico della
classe e, in ogni caso, mettere a nil l'istanza nel codice della
classe, significa spararsi sui piedi.