Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1

    [DELPHI 7] : Bug ?

    Salve,
    vorrei sapere un vostro parere in merito ad una questione .

    Ho creato due classi del tipo

    codice:
    	type 
    		TIndirizzo = class
    			constructor
    				create;
    			private
    				nome:string;
    				cognome:string;
    				citta:string;
    				via:string;
    				cap:string;
    			protected
    				procedure leggi(info:string);
    			public
    				property getnome: string read nome;
    				property getcognome: string read cognome;
    				property getcitta: string read citta;
    				property getvia: string read citta;
    				property getcap: string read citta;
    			end;
    			
    			TlistaIndirizzi = class
    				constructor create(nf:string);
    				private
    					indirizzi: array of TIniridzzo;
    				public
    					procedure get_indirizzo(nome:string;cognome:string):TIndirizzo;
    				end;
    		
    		....
    	implementation
    		procedure Tindirizzi.leggi(info:string);
    		begin
    			nome:=copy(info,1,10);
    			nome:=copy(info,20,10);
    			cognome:=copy(info,30,10);
    			citta:=copy(info,40,10);
    			via:=copy(info,50,10);
    			cap:=copy(info,60,10);
    		end;
    		..
    		procedure TListaIndirizzi.create(nf);
    		var
    			t:textFile;
    			i:integer;
    			riga:string;
    		begin
    			i:=0;
    			assignFile(t,nf);
    			reset(t);
    			while not eof(t) do
    			begin
    				readln(t,riga);
    				SetLength(indirizzi,i+1);
    				indirizzi[i]:=TIndirizzo.create;
    				indirizzi[i].leggi(riga);
    				inc(i);
    			end;
    			closeFile(t);
    		end;
    		...
    		var 
    			ListaInd:TlistaIndirizzi;
    			indirizzo:Tindirizzo;
    Se io eseguo il codice sottostante

    codice:
    	...
    		indirizzo:=Tindirizzo.create;
    		ListaInd:=TlistaIndirizzi.create('indirizzi.txt');
    		indirizzo:=ListaInd.get_indirizzo('Mario','Rossi');
    		showmessage(indirizzo.getcitta);
    		indirizzo.free;		
    	...
    Ottengo che il metodo free non solo cancella la variabile "indirizzo" ma anche "ListaInd.indirizzi[i]"!
    Questo mi fa pensare che ad "indirizzo" non venga passato il valore di ListaInd.indirizzi[i], ma l'indirizzo di memoria come se fosse un puntatore.. ma perchè? è normale?

    P.S.
    Il codice è un esempio semplificato di quello che fa la mia classe, non è il codice reale!
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,466
    Originariamente inviato da Whitecrowsrain
    Ottengo che il metodo free non solo cancella la variabile "indirizzo" ma anche "ListaInd.indirizzi[i]"!
    Cosa intendi con "cancellare"? Il metodo Free distrugge l'oggetto, pertanto qualsiasi riferimento a esso non sarà più valido perché questo non esiste più in memoria (ciò si tradurrà quindi in una probabile Access Violation).


    Originariamente inviato da Whitecrowsrain
    Questo mi fa pensare che ad "indirizzo" non venga passato il valore di ListaInd.indirizzi[i], ma l'indirizzo di memoria come se fosse un puntatore.. ma perchè? è normale?
    Il codice mi sembra abbastanza caotico, ad ogni modo è sufficiente sapere che quando si crea una istanza di una classe (oggetto), cioè di cui si dispone è il "riferimento" a quell'oggetto, cioè un "puntatore". Andando a richiamare il metodo Free, si distrugge l'oggetto in questione attraverso il suo riferimento, pertanto qualsiasi altro riferimento presente in variabili, campi, array o altre strutture dati non sarà più "valido" (avrà cioè un puntatore valido - non nil - ma che si riferisce a un oggetto che non esiste più).

    P.S.: suggerisco di usare titoli più significativi per i problemi (tralasciando il fatto che non è affatto un bug ciò che è alla base della programmazione a oggetti).
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Originariamente inviato da alka
    Cosa intendi con "cancellare"? Il metodo Free distrugge l'oggetto, pertanto qualsiasi riferimento a esso non sarà più valido perché questo non esiste più in memoria (ciò si tradurrà quindi in una probabile Access Violation).



    Il codice mi sembra abbastanza caotico, ad ogni modo è sufficiente sapere che quando si crea una istanza di una classe (oggetto), cioè di cui si dispone è il "riferimento" a quell'oggetto, cioè un "puntatore". Andando a richiamare il metodo Free, si distrugge l'oggetto in questione attraverso il suo riferimento, pertanto qualsiasi altro riferimento presente in variabili, campi, array o altre strutture dati non sarà più "valido" (avrà cioè un puntatore valido - non nil - ma che si riferisce a un oggetto che non esiste più).

    P.S.: suggerisco di usare titoli più significativi per i problemi (tralasciando il fatto che non è affatto un bug ciò che è alla base della programmazione a oggetti).
    Forse non mi sono spiegato bene, probabilmente perchè manca la funzione "get_indirizzo":

    codice:
    function TlistaIndirizzi.get_indirizzo(nome,cognome:string):Tindirizzo;
    var
      i:integer;
    begin
      result:=nil;
      for i:=0 to count(indirizzi)-1 do
      begin
        if (indirizz[i].nome=nome) and (indirizz[i].cognome=cognome) then
        begin
           result:=indirizz[i];
           break;
        end;
      end;
    
    end;
    Tornando al codice in esame:

    codice:
    indirizzo:=Tindirizzo.create;
    ListaInd:=TlistaIndirizzi.create('indirizzi.txt');
    indirizzo:=ListaInd.get_indirizzo('Mario','Rossi');
    showmessage(indirizzo.getcitta);
    indirizzo.free;
    quando faccio il free non solo mi libera la variabile "indirizzo" ma anche quella dal quale ha copiato il valore cioè quella di "ListaInd.indirizzi[i]" (risultato della funzione get_indirizzo), come se ad "indirizzo" non gli avesse assegnato solo il valore della variabile "ListaInd.indirizzi[i]", ma proprio l'indirizzo di memoria.. ma io non ho usato un puntatore.. ecco dov'è la mia perplessità e chiedevo se fosse normale o se fosse un bug!!
    Siccome mi sono confrontato con i miei colleghi qui in ufficio su questo argomento e mi dicevano che nella variabile "indirizzo" dovrebbe esser copiato solo il valore del risultato della funzione "get_indirizzo" e non l'indirizzo chiedevo se fossimo tutti in errore o se a sbagliare fosse il compilatore..

    Tu dici bene
    quando si crea una istanza di una classe (oggetto), cioè di cui si dispone è il "riferimento" a quell'oggetto, cioè un "puntatore"

    Ma qui io ho due istanze diverse, "indirizzo" ed il risultato di "ListaInd.get_indirizzo('Mario','Rossi')".. perché se libero la prima istanza mi dovrebbe liberare anche la seconda? E' normale? e se io volessi che in indirizzo venisse copiato solo il valore risultato della funzione?

    p.s: ottimo titolo, sinceramente non sapevo cosa scriverci!!
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  4. #4
    Originariamente inviato da Whitecrowsrain
    codice:
    indirizzo:=Tindirizzo.create;
    ListaInd:=TlistaIndirizzi.create('indirizzi.txt');
    indirizzo:=ListaInd.get_indirizzo('Mario','Rossi');
    showmessage(indirizzo.getcitta);
    indirizzo.free;
    Scusa, ma non stai usando la stessa variabile?

  5. #5
    Originariamente inviato da ESSE-EFFE
    Scusa, ma non stai usando la stessa variabile?
    dopo il free della variabile "indirizzo" se faccio di nuovo :

    codice:
      ListaInd.get_indirizzo('Mario','Rossi');
    ottengo come risultato nil, cioè non solo mi ha liberato la variabile "indirizzo" ma anche il risultato della funzione get_indirizzo, ovvero ListaInd.indirizzi[i] (che è di tipo TIndirizzo e dal quale ho copiato il valore su "indirizzo") !!
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  6. #6
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,466
    Originariamente inviato da Whitecrowsrain
    Forse non mi sono spiegato bene, probabilmente perchè manca la funzione "get_indirizzo"
    Forse dovresti postare tutto il codice, perché sicuramente lì c'è l'errore.

    Se guardiamo codice esemplificativo, magari quello non riconduce al problema.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  7. #7
    codice:
      //Definizione delle classi
      TFormato = class
        constructor create;
      private
        nome:string;
        codice:string;
        codice_man:string;
        codice_cd:string;
        alt:double;
        larg:double;
        quality:double;
        rapW:double;
        rapH:double;
        codici: array of string;
        limiti: array of string;
        variabile:boolean;
      protected
        procedure azzera;
        procedure leggi(nomeFormato,nf:string);
      public
        property getnome: string read nome;
        function getcodice: string;
        property getcodice_man: string read codice_man;
        property getcodice_cd: string read codice_cd;
        property getAlt: double read alt;
        property getLarg: double read larg;
        property getQuality: double read quality;
        property getRapW: double read rapW;
        property getRapH: double read rapH;
        function trovacodice(cod,formato:string):boolean;
        function getCodicePerSviluppo(sviluppo:double):string;
        property isVariabile: boolean read variabile;
      end;
      TListaFormati = class	
        constructor create(nf:string);
      private
    		nf_config:string;
        numero_formati:integer;
        formati: array of TFormato;
      public		
        function getFormatoByName(nome:string):TFormato;
        function getFormatoByID(id:integer):TFormato;
        function getFormatoName(id:integer):string;
        property getnumeroFormati: integer read numero_formati;
      end;
    	..
    	//funzioni
    	procedure TFormato.azzera;
    begin
      nome:='';
      codice:='';
      codice_man:='';
      codice_cd:='';
      alt:=0;
      larg:=0;
      quality:=0;
      rapW:=0;
      rapH:=0;
      SetLength(limiti,0);
      SetLength(codici,0);
      variabile:=false;
    end;
    constructor TFormato.create;
    begin
      azzera;
    end;
    function TFormato.getcodice: string;
    begin
      result:='';
      try
        if variabile then
          result:=codici[0]
        else
          result:=codice;
      except
      end;
    end;
    procedure TFormato.leggi(nomeFormato,nf:string);
    var
      ini:TiniFile;
      l,i:integer;
      lim,cod:string;
    begin
      azzera;
      if nomeFormato<>'' then
      begin
        ini:=TIniFile.Create(nf);
        nome:=nomeFormato;
        quality:=ini.ReadInteger(nomeFormato,'Quality',0);
        rapW:=ini.readFloat(nomeFormato,'Rapporto W',0);
        rapH:=ini.readFloat(nomeFormato,'Rapporto H',0);
        alt:=ini.readFloat(nomeFormato,'H',0);
        larg:=ini.readFloat(nomeFormato,'W',0);
        codice:=ini.readstring(nomeFormato,'codice','');
        codice_man:=ini.readstring(nomeFormato,'codice manuale','');
        codice_cd:=ini.readstring(nomeFormato,'codice automatico','');
        variabile:=ini.readstring(nomeFormato,'Tipo','F')='V';
        l:=ini.readInteger(nomeFormato,'Limiti',0);
        SetLength(limiti,l);
        SetLength(codici,l);
        if variabile then
        begin
          for i:=1 to l do
          begin
            limiti[i-1]:=ini.readstring(nomeFormato,'Limite'+inttoStr(i),'');
            codici[i-1]:=ini.readstring(nomeFormato,'Codice'+inttoStr(i),'');
          end;
        end;
    
        ini.free;
      end;
    end;
    function TFormato.trovacodice(cod,formato:string):boolean;
    var
      i:integer;
    begin
      result:=false;
      if formato=nome then
      begin
        if (cod=codice) or (cod=codice_man) or (cod=codice_cd) then
          result:=true;
        if not result then
        begin
          for i:=0 to length(codici)-1 do
          begin
            if codici[i]= cod then
            begin
              result:=true;
              break;
            end;
          end;
        end;
      end;
    end;
    function TFormato.getCodicePerSviluppo(sviluppo:double):string;
    var
      i:integer;
      l:double;
    begin
      result:='';
      for i:=0 to length(limiti)-1 do
      begin
        l:=strToFloatDef(limiti[i],-1);
        if l=-1 then
        begin
          result:=codici[i];
          break;
        end
        else begin
          if sviluppo<=l then
          begin
            result:=codici[i];
            break;
          end;
        end;
      end;
    end;
    constructor TListaFormati.create(nf:String);
    var
      ini:TiniFile;
      lf:Tstringlist;
      i:integer;
    begin
    	nf_config:=nf;
      lf:=TStringList.create;
      ini:=TIniFile.Create(nf);
      ini.ReadSections(lf);
      ini.Free;
      numero_formati:=lf.Count;
      SetLength(formati,numero_formati);
      for i:=0 to numero_formati-1 do
      begin
        formati[i]:=TFormato.create;
        formati[i].leggi(lf[i],nf);
      end;
      lf.free;
    end;
    function TListaFormati.getFormatoByName(nome:string):TFormato;
    var
      i:integer;
      ris:TFormato;
    begin
      ris:=TFormato.create;
    
      for i:=0 to numero_formati-1 do
      begin
        if nome=formati[i].getnome then
        begin
          ris:=formati[i];
          break;
        end;
      end;
      Result:=ris;
    end;
    function TListaFormati.getFormatoName(id:integer):string;
    begin
      try
        result:=Formati[id].getnome;
      except
        result:='';
      end;
    end;
    function TListaFormati.getFormatoByID(id:integer):TFormato;
    var
      ris:TFormato;
    begin
      ris:=TFormato.create;
      if numero_formati<id then
        ris:=Formati[id];
      result:=ris;
    end;
    Ok ora se provo a fare questo:

    codice:
    var	
    	lista:TlistaFormati;
    	formato1,formato2:TFormato;
    begin
    	lista:=TlistaFormati.create('formati.ini');
    	formato1:=TFormato.create;
    	formato1:=lista.getFormatoByName('PICCOLO');
    	showmessage(formato1.getnome);
    	formato1.free;
    	formato2:=TFormato.create;
    	formato2:=lista.getFormatoByName('PICCOLO');
    	showmessage(formato2.getnome);
    	formato2.free;
    	
    end;
    Il risultato che ottengo del primo showmessage è "PICCOLO" mentre del secondo è ""... l'elemento "formati" dell'oggetto "lista" si è cancellato insieme alla variabile "formato1"!
    Inpratica quando ho assegnato a fomato1 il risultato della funzinoe "lista.getFormatoByName" gli ha passato l'indirizzo a quella variabile e non il valore!
    mi chiedo è normale? perché accade ciò?
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  8. #8
    Originariamente inviato da Whitecrowsrain
    codice:
    	formato1:=TFormato.create;
    	formato1:=lista.getFormatoByName('PICCOLO');
    Non so se c'entra direttamente con il problema che hai, però a me pare che stai chiamando TFormato.create una volta di troppo, sia prima della getFormatoByName, che all'interno della stessa funzione (ris:=TFormato.create).

  9. #9
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,466
    Concentriamoci su questo punto:

    codice:
    	lista:=TlistaFormati.create('formati.ini');
    	formato1:=TFormato.create;
    	formato1:=lista.getFormatoByName('PICCOLO');
    	showmessage(formato1.getnome);
    	formato1.free;
    	formato2:=TFormato.create;
    	formato2:=lista.getFormatoByName('PICCOLO');
    	showmessage(formato2.getnome);
    	formato2.free;
    Innanzitutto, ci sono delle chiamate a TFormato.Create che non servono a nulla, perché la variabile viene riassegnata subito dopo usando la getFormatoByName.

    Poi, chiamando la getFormatoByName, si ottiene il riferimento a un oggetto che viene memorizzato in "formato1", di cui si fa la Free; pertanto, quell'oggetto viene distrutto, e il riferimento contenuto in "formato1" non sarà più valido.

    Successivamente, sempre tramite la getFormatoByName, si ottiene lo stesso formato (PICCOLO) che non esisterà più perché distrutto poco prima.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  10. #10
    Originariamente inviato da alka
    Concentriamoci su questo punto:

    codice:
    	lista:=TlistaFormati.create('formati.ini');
    	formato1:=TFormato.create;
    	formato1:=lista.getFormatoByName('PICCOLO');
    	showmessage(formato1.getnome);
    	formato1.free;
    	formato2:=TFormato.create;
    	formato2:=lista.getFormatoByName('PICCOLO');
    	showmessage(formato2.getnome);
    	formato2.free;
    Innanzitutto, ci sono delle chiamate a TFormato.Create che non servono a nulla, perché la variabile viene riassegnata subito dopo usando la getFormatoByName.

    Poi, chiamando la getFormatoByName, si ottiene il riferimento a un oggetto che viene memorizzato in "formato1", di cui si fa la Free; pertanto, quell'oggetto viene distrutto, e il riferimento contenuto in "formato1" non sarà più valido.

    Successivamente, sempre tramite la getFormatoByName, si ottiene lo stesso formato (PICCOLO) che non esisterà più perché distrutto poco prima.
    Ora ho capito, pero:
    non capisco perché si ottiene il riferimento all'oggetto e non il valore dell'oggetto, io non gli passo un puntatore, ma faccio una assegnazione.
    Di conseguenza mi aspettavo che a formato1 venisse copiato il valore dell'oggetto risultato della funzione e non che invece venisse assegnato il riferimento all'oggetto stesso.
    E' ovvio che in quest'ottica diventa superfluo creare gli oggetti formato1 e formato2..

    Per ottenere il risultato da me sperato dovevo fare una cosa del genere:

    codice:
      //Aggiungere una funzione assign a TFormati
      Prodecdure TFormati.assign(Var FormatoInCuiCopiare:TFormato);
      var
        i:integer;
        begin
          if FormatoInCuiCopiare<>nil then
          begin
            FormatoInCuiCopiare.nome:=nome;
    	FormatoInCuiCopiare.codice:=codice;
    	FormatoInCuiCopiare.codice_man:=codice_man;
    	FormatoInCuiCopiare.codice_cd:=codice_cd;
    	FormatoInCuiCopiare.alt:=alt;
    	FormatoInCuiCopiare.larg:=larg;
    	FormatoInCuiCopiare.quality:=quality;
    	FormatoInCuiCopiare.rapW:=rapW;
    	FormatoInCuiCopiare.rapH:=rapH;
    	setLength(FormatoInCuiCopiare.codici,length(codici));
    	setLength(FormatoInCuiCopiare.limiti,length(limiti));
    	for i:=0 to count(codici)-1 do
              FormatoInCuiCopiare.codici[i]:=codici[i];
    	for i:=0 to count(limiti)-1 do
    	  FormatoInCuiCopiare.limiti[i]:=limiti[i];
    			
    	limiti: array of string;
    	FormatoInCuiCopiare.variabile:variabile;
        end;		
      end;
    A quel punto avrebbe avuto senso scrivere così:

    codice:
      lista:=TlistaFormati.create('formati.ini');
      formato1:=TFormato.create;
      lista.getFormatoByName('PICCOLO').assign(formato1);
      showmessage(formato1.getnome);
      formato1.free;
      formato2:=TFormato.create;
      lista.getFormatoByName('PICCOLO').assign(formato2);
      showmessage(formato2.getnome);
      formato2.free;
    ed avrei raggiunto il risultato sperato, giusto?
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.