Newsgroup: it.comp.lang.delphi
Titolo: Invalid pointer operation

Ricevo il messaggio di errore in oggetto in questa riga del FormClose:
   BudgetsList.Free;
 
Questa TObjectList è dichiarata cosi' (insieme alla classe le cui istanze 
poi aggiunge alla lista):
var
  BudgetsList: TObjectList;
  oMensili: TMensili;
e usata come segue:
 
BudgetsList:= TObjectList.Create(true);
do while ....
     oMensili:= TMensili.Create(...);
     BudgetsList.Add(oMensili);
end;
 
Come chiudo il form dà l'errore di Invalid Pointer operation; insistendo più 
volte a chiudere il form, poi lo chiude. Qualche idea ? 
 

 ha scritto:

La visibilità di quella variabile qual'è? l'hai dichiarata come variabile 
del form o variabile locale di una funzione/procedura?
 


Variabile del form. Ho provato a indagare sul count della Lista prima del 
free per vedere se conteneva il num degli oggetti ch mi aspettavo e sono 
correttamente 42. Poi fa il free, dà l'errore e insistendo  sulla chiusura 
del form questa volta il count dà come risultato 3 e infine zero. A questo 
punto chiude. Molto strano. Non faccio il free di nessuno degli oggetti 
della lista nel corso del programma. 
 

 correttamente 42. Poi fa il free,
 
Il free di cosa?
 
 


Pero' da come descrivi il problema sembra proprio che l'errore
esca durante la distruzione di uno degli oggetti contenuti nella lista.
 
Direi che ti conviene ridefinire il distruttore degli oggetti TMensile 
eccetera in modo da vedere cosa succede durante la distruzione.
 
G
 
 
 
 
 

 end;
 
 
 
A.
 
 


Il free di BudgetsList. In questa proc di chiusura del form:
 
procedure TBudgetMainForm.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  BudgetTable.Close;
  DBGridBTable.Close;
  showmessage('List count prima di free:'+inttostr(BudgetsList.Count));
  BudgetsList.Free;//MyObject is also freed since the TObjectList was 
created with the OwnsObjects property set to true.
end;
 

 ha scritto nel messaggio 
news:8ff53d11-9207-439d...@googlegroups.com...
Serve il codice che sta sulla close/free del form.
 
 
a cosa serve avere oMensili in var?
Se e' usata solo localmente per popolare la lista deve essere dichiarata 
come locale nel realtivo metodo.
 
BudgetList: se è usata solo dal form, metti la dichiarazione nella sezione 
private.
 
Aggiungo: non usare MAI variabili globali.
 
Quante righe si smazza il while?
 
A.
E' vero: quanto sopra è appropriato: in effetti oMensili mi serve solo 
localmente e metterò BudgetsList nella sez private. Il codice in chiusura è 
il seguente:
 
procedure TBudgetMainForm.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  BudgetTable.Close;
  showmessage('List count prima di free:'+inttostr(BudgetsList.Count));
  BudgetsList.Free;
end;
 
 

 ha scritto nel 
messaggio news:ab4d4a96-b579-42da...@googlegroups.com...

Il destructor fa il free di FMensiliB che è una StringList:
destructor TMensiliB.Destroy;
begin
   FMensiliB.Free;
   Inherited Destroy;
end;
 
 
 
 
 

Sposta la logice che adesso sta in Onclose sulla OnDestroy.
 
Se scoppia ancora prova a SOSTITUIRE TObjectList con tList.
Okkio: 
devi prp sostituire e non invocare il costruttore di tObjectList passando False 
come parametro.
 
Poi:
 
procedure TBudgetMainForm.FormDESTORY(Sender: TObject);
var
  TempObj: TMensili;
begin
  TRY
    BudgetTable.Close;
  EXCEPT
    on E:Exception do
    begin
      log('closing  BudgetTable:' + E.ClassName + ' ' +E.Message);
    end;
  END;
 
  try
    DBGridBTable.Close;
 
  EXCEPT
    on E:Exception do
    begin
      log('closing  DbgridTable: ' + E.ClassName + ' ' +E.Message);
    end;
  END;
 
  try
    for i :=  Pred(BudgetsList.Count) do
    begin
      try       
        tempObj := TMensili(BudgetsList[i]);
      except
        on E:Exception do
        begin
          TempObj := nil; 
          log('closing  cast:' + E.ClassName + ' ' +E.Message);
        end;
      end; 
 
      if (Assigned(TempObj)) then
      begin
        try
          FreeAndNil(TempObj)
 
        except
          on E:Exception do
          begin
            log('free :' + E.ClassName + ' ' +E.Message);
          end;
        end;   
      end;
    end;  
 
 except
  on E:Exception do
  begin
    log('generic cast:' + E.ClassName + ' ' +E.Message);
  end;
 end; 
 
 

provo.

Problema trovato ! Grazie a tutti. Ecco cos'era:
 
var
   ListaTemp: TStringList;
   .......................
   ListaTemp:= TMensiliB ( BudgetsList[i] ).GetMensili );
   ......................
   ListaTemp.Free;
 
ListaTemp era una StringList definita in locale che usavo per trasferire i 
valori in una serie di edits: E' il suo Free che ovviamente (adesso!) 
causava l'errore. Non mi ero reso conto che cancellavo il riferimento nella 
ObjectList.
 
Mi viene da approfittare per fare una domanda che non c'entra nulla: se 
voglio puntare all'oggetto della ObjectList la cui proprietą ID č uguale a 
quello che gli vorrei passare, come faccio ? 
 

 quello che gli vorrei passare, come faccio ?
 
cicli, casti e fai un cofronto.
 
A.
 

 
cicli, casti e fai un cofronto.
 
A.
Ho fatto qualcosa del genere, ma avrei voluto usare IndexOf, ma non capisco 
come funziona, visto che richiede come parametro un oggetto, mentre io 
voglio trovare uno specifico oggetto. 
 

 come funziona, visto che richiede come parametro un oggetto, 
 
Rifletti..
TList e TObjectList contengono dei TObject e non i tuoi oggetti.
Questo ti obbliga a fare un cast.
Quale e' la soluzione?
 
A.
 
 
 
 

 ha scritto nel messaggio 
news:b8f073c3-5c99-42ef...@googlegroups.com...

Vuoi dire che non contengono l'oggetto, ma il puntamento all'oggetto, vero? 
Per� non ho ancora capito il typecast. Ho provato con :
    TMensili(BudgetsList[BudgetsList.IndexOf(.......)]).GetMensili);
ma non capisco cosa devo metterci al posto dei puntini. 
 

 ma non capisco cosa devo metterci al posto dei puntini.
Ok. visto che 6 fuori strada di to una dritta.
 
TList/ToBjectList non possono per ovvi motivi avere un find basato su una qualsiasi property di una classe definita da te....
Giusto?
Ma nessuno ti obbliga a usare per forza TList/TObjectList.
Cosa ti impedisce di crearti una tua classe che gestisce una collection TIPIZZATA di oggetti come quelli che usi tu?
A quel punto, questa classe, guarda caso, potrebbe esporre un metodo per fare la ricerca che ti serve....
 
A.
 
 
 
 
 
 

 ha scritto nel messaggio 
news:f862ffad-33c8-4a70...@googlegroups.com...

Ancora non vedo la soluzione. Dovrei storizzare i miei oggetti in una 
TCollection (di cui finora ho solo sentito dire..) e creare un metodo di 
questa TCollection che cicla nei suoi item per ritornare quello uguale a 
quellom che gli passo come parametro ? E' circa cosi' ?
 
Nel frattempo io avevo fatto quello che sicuramente giudicherai una cazzata, 
che è la funzione seguente:
 
function TBudgetMainForm.GetPosInlist(aCat: string): integer;
var
  i,j: integer;
begin
  j:= 0;
  for i:=0 to BudgetsList.Count-1 do
  begin
   { Scorri la Lista BudgetsList (oggetti di classe TMensili) e trova
     in che posizione si trova l'oggetto che ha il valore aCat nella
     sua proprietà Cat }
     if Trim(aCat) = Trim(TMensili(BudgetsList.Items[i]).GetCat) then
        break;
     j:=j+1;
  end;
  result:= j;
end;
 
e poi  per reperire i valori di una specifica Categoria:
 
ListaTemp:= TMensili(BudgetsList[GetPosInList('unaCat')]).GetMensili);
 
 
 
 
 

 che è la funzione seguente:
 
 
Infatti e' una cazzata. Adesso dimmi tu xche lo e'....
 
A

 end;
 
L'idea concettualmente è corretta (scorro la lista di oggetti finchè non 
trovo quello cercato, e ritorno il suo indice), tuttavia non tieni conto 
che delphi fornisce già degli oggetti che possono fare questo lavoro per te.
Esiste la TList che ti permette di memorizzare in una collezione tutti 
gli oggetti che vuoi e di fare le operazioni di ricerca, ordinamento, 
estrazione di questi oggetti.
Tieni presente che la tlist non possiede gli oggetti che gli aggiungi, 
quindi se dovrai liberare la memoria dovrai farlo tu esplicitamente.
Se invece vuoi demandare alla lista la capacità di liberare la memoria, 
usa TObjectList che, rispetto alla TList, implementa l'ownership degli 
oggetti che gli aggiungi.
 
http://www.delphibasics.co.uk/RTL.asp?Name=TList
 
 
 
 
 
-- 
morde
Android
QT 4.7
Delphi (5,6,7.. expired)
Firebird Database
 

> 
http://www.delphibasics.co.uk/RTL.asp?Name=TList
 
 
grazie Morde con un esempio così sono riuscito a capirlo anch'io, ciao Brunello

La soluzione migliore e' avere una propia classe collection che:
 
a) incapsula una TList/Tobjectlist
b) espone membri per insert, add, remove etc
c) espone membri gia tipizzati per leggere il tipo di oggetto che gestisci incapsulando i typecast
d) espone, opportunamente mappate, le caratteristiche di TList/TObjectList legate al sort e agli iteratori
 
In questo modo HAI UNA CLASSE COMPLETA RIUTLIZZABILE INDIPENDENTE, che può funzionare senza cose esterne.
 
Una classe dovrebbe, per quanto essere possibile, essere progettata sulla logica del "puoi ma non e' detto che devi".
 
La soluzione proposta da te implica l'esistenza di una PROCEDURA.
che *non puoi mettere in una classe come metodo*: devi tenerla fuori.
 
Se ti serve questa cosa in piu form/contesti, ti tocca avere una unit che 
espone una procedure globale usata da tutti: brrrrrrrrrrrrrrrrrrrrr!
 
Ovviamente qualche "einstein" potrebbe dire "prendo quel pezzo di codice e lo copio dove mi serve cosi non ho cose globali: doppio brrrrrrrrrrrrrrrrrrrrr!
 
 
A.
 
 
 
 
 
 
 
 
 
 
 

 ha scritto nel messaggio 
news:23eec12c-6602-42e0...@googlegroups.com...

Grazie davvero, non so ancora se ho capito al punto di fare da me, ma ci 
provo. Non so se ce la faccio prima di sabato, quando me ne andrò a passare 
un po' di tempo a Rimini, tornando tra parenti e vecchi amici..
 
 
 
 
 
 
 
 
 
 
 

 passare un po' di tempo a Rimini, tornando tra parenti e vecchi amici..
 
Mi raccomando, controlla il quoting, non riesco a distinguere la tua 
risposta dal quoting del post precedente.
:)


 d) espone, opportunamente mappate, le caratteristiche di TList/TObjectList legate al sort e agli iteratori
 
Se poi hai una versione di delphi abbastanza recente, la cosa "piu' migliore"
e' di usare i generics cosi' queste cose sono gia' disponibili e non
devi sbatterti a implementarle tu! :)
 
 
ciao
G
 

 ha scritto nel messaggio 
news:23eec12c-6602-42e0...@googlegroups.com...
La soluzione migliore e' avere una propia classe collection che:
 
a) incapsula una TList/Tobjectlist
b) espone membri per insert, add, remove etc
c) espone membri gia tipizzati per leggere il tipo di oggetto che gestisci 
incapsulando i typecast
d) espone, opportunamente mappate, le caratteristiche di TList/TObjectList 
legate al sort e agli iteratori
A.
 
Allora, sto provando come segue (non sono stato bravo, ho trovato un piccolo 
esempio adattabile..).
Il mio principale problema era indirizzare nella lista un oggetto specifico 
senza conoscerne l'indice. Ho fatto il metodo FindItem, ma non mi pare che 
vada bene perchè oltre alla stringa di rierca che specifica l'oggetto che 
cerco, ho dovuto passargli anche un riferimento all'oggetto. E' giusto ? Ma 
quale riferimento gli passo ? Isomma, faccio ancora confusione !
 
type
  TListOfBudgets = class(TObjectList)
  private
    function  GetItems(Index: integer): TMensiliB;
    procedure SetItems(Index: integer; value: TMensiliB);
  public
    constructor Create;
    function  Add(Value: TMensiliB): integer;
    function  FindItem(aCat: string; Value: TMensiliB): TMensiliB;
    property  Items[Index: integer]: TMensiliB read GetItems write SetItems; 
default;
  end;
 
constructor TListOfBudgets.Create;  // creazione classe TListaOfBudgets
begin
   // Imposta la ObjectList x possedere gli oggetti
   inherited Create (true);    // Owns objects
end;
 
function  TListOfBudgets.FindItem(aCat: string; Value: TMensiliB): 
TMensiliB;
var i: integer;
begin
  result:= nil;
 for i:= 0 to Self.Count-1 do
   if Valu.GetCat = aCat then
      result:= Value;
end;
 
function TListOfBudgets.Add(Value: TMensiliB): integer;
begin
  result:= inherited Add(value);
end;
 
function TListOfBudgets.GetItems(Index: integer): TMensiliB;
begin
  result:= TMensiliB(inherited Items[Index]);
end;
 
procedure TListOfBudgets.SetItems(Index: integer; Value: TMensiliB);
begin
  inherited Items[Index]:= value;
end;
 
 

 ha scritto nel 
messaggio news:26e7b7bb-5a35-421f...@googlegroups.com...
 
Se poi hai una versione di delphi abbastanza recente, la cosa "piu' 
migliore"
e' di usare i generics cosi' queste cose sono gia' disponibili e non
devi sbatterti a implementarle tu! :)
ciao
G
Generics ? Lavoro con DelphiWin32, ci sono ? 
 

Sono nell'intervallo della partita e ce l'ho fatta ! Ecco la FindItem 
giusta:
 
function  TListOfBudgets.FindItem(aCat: string):TMensiliB;
var i: integer;
begin
  result:= nil;
 for i:= 0 to Self.Count-1 do
   if Self.Items[i] = aCat then
      result:= Self.Items[i];
end;
 
Bene! Ora posso andare in vacanza, non prima di aver ringraziato tutti. 
Grazie al problema Invalid Pointer operation ho imparato un sacco di cose: 
Non tutti i mali vengono per nuocere!
 
 
 
 
 
 
 

Stark ha usato la sua tastiera per scrivere :

ehm...sei proprio sicuro??
mi pare tu faccia un confronto tra un TMensiliB e una String (if 
Self.Items[i] = aCat).
 
-- 
Emanuele Desideri
 
 

 Self.Items[i] = aCat).
 
Si infatti. :)
Dovrebbe diventare una cosa simile (vado a memoria):
 
if (Self.Items[i] as TMensiliB).aCat = aCat then
       result:= Self.Items[i];
 
il cast sul ritorno dovrebbe farlo in automatico il compilatore.
 
Unica pecca, l'iterazione seriale su tutta lista: più efficente sarebbe 
stato che TListofBudget avesse al suo interno una mappa, e il metacodice 
diventerebbe:
 
function  TListOfBudgets.FindItem(aCat: string):TMensiliB;
begin
	result := self._mappa.Find(aCat);
end;
 
quella find ha un tempo di ricerca logaritmico, il più basso in assoluto.


 
type
  TListOfBudgets = class(TObjectList)
  private
    function  GetItems(CONST Index: integer): TMensiliB;
    procedure SetItems(CONST Index: integer; value: TMensiliB);
  public
    constructor Create;
    function  Add(Value: TMensiliB): integer;
    function  FindItem(CONST aCatEGORY: string): TMensiliB;
    property  Items[CONST Index: integer]: TMensiliB read GetItems write SetItems;
default;
  end;
 
constructor TListOfBudgets.Create;  // creazione classe TListaOfBudgets
//A COSA SERVE QUESTO COMMENTO??         ^^^^^^^^^^^^^
//LO VEDO DA ME CHE E' UN COSTRUTTORE...  
 
begin
   // Imposta la ObjectList x possedere gli oggetti
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ COME SOPRA
 
   inherited Create (true);    // Owns objects
                               ^^^^^^^^^^^^^^^^^^^ COME SOPRA: COMMENTO INUTILE 
end;
 
function  TListOfBudgets.FindItem(CONST aCatEGORY: string:
TMensiliB;
 
var 
  i: integer;
begin
  result:= nil;
 for i:= 0 to Self.Count-1 do
 BEGIN
   if ITEMS[I].GetCat = aCatEGORY then
   BEGIN
      result:= Value;
      BREAK; //<<<===============
   END;
 END;
end;
 
function TListOfBudgets.Add(Value: TMensiliB): integer;
VAR
  I: INTEGER;
  TEMPITEM: TBENSILIB;
 
begin
  RESULT := -1;
 
  IF (NOT ASSIGNED(VALUE)) THEN
  BEGIN
    // SE NON FACESSI COSI NELLA LISTA POTERI AVERE DEI NIL
    // CHE POTREBBERO MANDARE TUTTO AI FESTINI DEL NANO DI ARCORE 
    LOG('VALUE IS NIL!');
    EXIT; 
  END;
 
  TEMPITEM := FIND(
VALUE.CAT
);
  IF (ASSIGNED(TEMPITEM)) THEN
  BEGIN
    // SE NON FACESSI COSI NELLA LISTA POTERI AVERE 
    // ELEMENTI DIPLICATI CHE FANNO CASINO
    LOG('DUPLICATE ELEMENT FOR:' 
VALUE.CAT
);
    EXIT;
  END;
 
  result:= inherited Add(value);
 
end;
 
function TListOfBudgets.GetItems(CONST Index: integer): TMensiliB;
VAR
  OBJ: TOBJECT;
begin
  RESULT := NIL;
  OBJ := inherited Items[Index];
  IF (ASSIGNED(OBJ)) THEN
  BEGIM
    result:= TMensiliB(OBJ);  
  END;
end;
 
procedure TListOfBudgets.SetItems(CONST Index: integer; Value: TMensiliB);
begin
  inherited Items[Index]:= value;
end; 
 
 
Alcune dritte:
 
1) un commento non deve speigare quello che il codice fa ma xche lo fa
2) sarebbe meglio non avere commenti in linea
3) usa SEMPRE il qualificatore const/var nei parametri di metodi, funzioni procedure
 
A.
 
 
 

   END;
 
Ciao Alberto,
scusa ma, la scelta di avere o non avere duplicati è sicuramente una 
scelta fondamentale, ma non credo possa essere a prescindere.
E' chiaro che se si sceglie di poterli avere, vanno gestiti.
O sbaglio?
 
-- 
Emanuele Desideri
 
 


Si, si mi è rimasto nella tastiera, ma funziona. La riga e' in effetti:
    if items[I].GetCat = aCat then
 
Grazie dei commenti ad Alberto. Implementero' meglio la cosa seguendoli.
Vado via Domenica, ho ancora tempo.
 
 

 Vado via Domenica, ho ancora tempo.
 
Non c'è niente di peggio che stare al mare e pensare allo sviluppo 
lasciato in sospeso :-[ :oÞ
 
-- 
Emanuele Desideri
 
 

 lasciato in sospeso :-[ :oï¿œ
 
Beh il peggio c'ï¿œ: sviluppare in ufficio pensando di stare al mare..
non quale dei due sia piï¿œ dannoso :-D


Se si tratta di DATI APPLICATIVI, una cosa che rompe assai le "sfere" e' avere una collection (o una tabella di database) priva di un "qualcosa" che identifichi in modo univoco un elemento.
Il codice che ho postato parte dal presupposto che tale valore univoco sia la categoria...Ma potrebbe essere un altro dato o un set di dati.
 
Immagina una TObjectList che contiene due reference allo stesso oggetto..
 
 
A.
 
 

 A.
 
eh no, due reference allo stesso oggetto no, ma a due oggetti uguali 
perchè no?!
o meglio, il perchè si lo capisco bene, io uso sempre un ID univoco, ma 
concettualmente non è detto che non possa avere nella stessa collection 
due oggetti uguali (e non due reference allo stesso oggetto!).
ovviamente poi come gestirli è altro discorso...
 
-- 
Emanuele Desideri
 
 

 perchè no?!
 
Si ma stai facendo un ragionamento accademico.. lo sappiamo tutti che 
due oggetti uguali potrebbero avere references diversi.. ecc.. [1].
 
Anyway, quello che vuol farti capire alberto è che nella tua collezione 
avere due oggetti uguali ti pone davanti al problema opposto: il metodo 
find, quale item deve ritornare se ne trova più di uno con la stessa chiave?
 
 
[1]
In java per determinare se due oggetti sono uguali devi soddisfare 
contemporaneamente ben quattro condizioni: riflessione, simmetria, 
transitività, non nullo. Lo vuoi implementare anche per i tuoi items o 
ti accontenti del controllo sull'ID ?


 item deve ritornare se ne trova più di uno con la stessa chiave?
è una situazione che va gestita, sono daccordo.
Io non mi pongo il problema, ho detto prima che uso un ID univoco, ma 
visto che mi sembrava che chi avesse aperto il topic cercasse di 
imparare l'uso delle collection, dare per scontato che dentro 2 oggetti 
"uguali" NON CI DEVONO essere mi sembrava accademicamente scorretto :D
 
ovviamente nessuna polemica, cercavo solo di capire io, e far capire 
che la presa di posizione di alberto, peraltro corretta, deve essere 
una scelta di progetto e non vincolata al come si usano le collection. 
B-)
 
-- 
Emanuele Desideri
 
 

 scelta di progetto e non vincolata al come si usano le collection. B-)
 
Totally agreed :)


 Generics ? Lavoro con DelphiWin32, ci sono ?
 
Si, a partire da D2009.
 
G