Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15

Hybrid View

  1. #1
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308

    [C#/Xna] Questa sconosciuta Garbage

    Ho realizzato in Xna un programma fantascientifico che permette la navigazione in un sistema planetario. Gli oggetti sono costruiti tramite moltissime strutture, alcune molto leggere che descrivono un pianeta "in lontananza" (modelli "Far", le cui istanze sono semplici sfere nude), ed altre molto pesanti per i grossi pianeti da sorvolare o da esplorare al suolo (modelli "Near", con milioni di primitive modellati da heightmaps e ricoperti da textures). E' impossibile postare il codice ma il riassunto del Main è qui:

    codice:
    //Namespaces
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using System;
    using System.Collections;
    using System.Windows.Forms;
    using System.Collections.Generic;
    namespace Progetto_Albireo   
    {
        public class My : Microsoft.Xna.Framework.Game
        {
            //Generals          
            public static GraphicsDeviceManager Graphicsdevicemanager;
            .............
            public static string StarType = "Progetto_Albireo.Star"; MODELLO STELLA 'FAR' (leggero)
            public static string TStarType = "Progetto_Albireo.TStar"; MODELLO STELLA 'NEAR' (leggero)
            //Worlds
            public static string SphType = "Progetto_Albireo.SphWorld"; MODELLO PIANETA 'FAR' (leggero)
            public static string SphHType = "Progetto_Albireo.SphHWorld";  MODELLO PIANETA 'NEAR' (molto pesante)
            ..... ecc.
            //FUNZIONI DI UTILITY
            public static float VelocityAt(float G, float M, float d)
            {
                return (float)Math.Sqrt(G * M / d);
            }
            .......... ecc.
            //METODO CHE INIZIALIZZA IL SISTEMA
            public void InitSystem()
            {
                Planets.Add("A", new Star(...);    
    
                Planets.Add("B", new SphWorld(....);  
                ................ ecc.
     
            }
     
            public My()
            {
                //costruiamo un nostro GraphicsDeviceManager
                //la sua proprietà più importante è il GraphicsDevice
                Graphicsdevicemanager = new GraphicsDeviceManager(this);
                Content.RootDirectory = "Content";
            }
    
            protected override void Initialize()
            {
                Spritebatch = new SpriteBatch(GraphicsDevice);
                ........... ecc.
                base.Initialize();
            }
            protected override void LoadContent()
            {
                Background = Content.Load<Texture2D>("back");
                
                ............. ecc.
                InitSystem();
            }
            protected override void Update(GameTime gametime)
            {
                My.Discovery.Depthlist.Clear(); LISTA DEGLI OGGETTI 
                                                IN ORDINE DI DISTANZA DALLA CAMERA (astronave)
                TStar.H1("A"); METODO STATICO CHE TRASFORMA "A" DA 'Sta'r IN 'TStar' 
                               SE CI SI AVVICINA TROPPO E LO RIPORTA A 'Star' SE CI SI ALLONTANA; 
                               AGGIORNA LA Dephtlist                     
                SphHWorld.H1("B", 0f, Vector3.Zero); METODO STATICO CHE TRASFORMA "B" DA 'SphWorld' IN 'SphHWorld'
                                                      SE CI SI AVVICINA TROPPO E LO RIPORTA A 'SphWorld' SE CI SI ALLONTANA;
                                                      AGGIORNA LA Dephtlist  
                .......... ecc.
            }
    
            protected override void Draw(GameTime gametime)
            {
                GraphicsDevice.Clear(Color.Black);
                 
      
                string T;
                foreach (KeyValuePair<double, string> item in Discovery.Depthlist)
                {
                    double d = item.Key;
                    string k = item.Value;
                    T = My.Planets[k].GetType().ToString();
                    if (T == My.StarType)
                    {
                        Star x = (Star)Planets[k];
                        x.Draw(GraphicsDevice);
                    }
                    else if (T == My.TStarType)
                    {
                        TStar x = (TStar)Planets[k];
                        x.Draw(GraphicsDevice);
                    }
                    else if (T == My.SphType)
                    {
                        SphWorld x = (SphWorld)Planets[k];
                        x.Draw(GraphicsDevice);
                    }
                    else if (T == My.SphHType)
                    {
                        SphHWorld x = (SphHWorld)Planets[k];
                        x.Draw(GraphicsDevice);
                    }
                    else if ........... ecc.
                }
     
            }
    
        }
    }
    

    Il cuore del programma è il metodo statico H1 che opera la trasformazione da "Far" a "Near" e viceversa. Questo è il riassunto:


    codice:
     
            public static void H1(string k, float FM, Vector3 L)
            {
                if (My.Planets[k].GetType().ToString() == My.SphType)
                {
                    SphWorld x = (SphWorld)My.Planets[k];
                    Vector3 d = My.Discovery.Position - x.Location;
                    //costruisce la collection di profondità
                    double D = Math.Sqrt((Math.Pow(d.X, 2) + Math.Pow(d.Y, 2) + Math.Pow(d.Z, 2)));
                    My.Discovery.Depthlist.Add(-D, k);
    
                    ...
                    //Solving
                    if (d.Length() < x.Ehorizon)
                        SphHWorld.Solve(k); 'TRASFORMA x NEL TIPO 'SphHWorld'
                }
                else
                {
                    SphHWorld x = (SphHWorld)My.Planets[k];
                    Vector3 d = My.Discovery.Position - x.Location;
                    //costruisce la collection di profondità
                    double D = Math.Sqrt((Math.Pow(d.X, 2) + Math.Pow(d.Y, 2) + Math.Pow(d.Z, 2)));
                    My.Discovery.Depthlist.Add(-D, k);
                    ...
                    //Unsolving
                    if (d.Length() > x.Ehorizon)
                        SphHWorld.Unsolve(k);'RIPORTA x IN AL TIPO 'SphWorld'
                }
            }
    

    Ecco in dettaglio i due metodi "decisivi" richiamati da H1:


    codice:
            public static void Solve(string k)
            {
                .........
    
                My.Planets.Remove(k);
     
                My.Planets.Add(k, new SphHWorld(...);
     
            }
            public static void Unsolve(string k)
            {
                ..........
    
                My.Planets.Remove(k);
    
                My.Planets.Add(k, new SphWorld(...);
            }
    

    Per avere la piena padronanza di questo programma mi manca solo di capire bene cosa succede QUI e QUI, ma soprattutto QUI:

    codice:
            public static void Solve(string k)
            {
    
                My.Planets.Remove(k);<<<<<------------------- QUI
     
                My.Planets.Add(k, new SphHWorld(...);
     
            }
            public static void Unsolve(string k)
            {
    
                My.Planets.Remove(k);<<<<<-------------------- QUI
     
                My.Planets.Add(k, new SphWorld(...);
            }
    
    Non capisco un tubo di Garbage Collection. Vorrei capire se l'oggetto k in hastable viene rimosso anche dalla memoria oltre che dall'hash, e se navigando negli spazi aperti lontano dal sistema non ci sono in memoria oggetti "Near" residenti. Un oggetto SphHWorld è veramente ingombrante....
    Spero di essere stato chiaro. Grazie
    Ultima modifica di escocat; 02-11-2013 a 16:11

  2. #2
    Nel momento in cui non ci sono più riferimenti ad un certo oggetto raggiungibili dal tuo programma, un oggetto diventa passibile di garbage collection; questo significa che, quando il runtime decide che si sta consumando troppa memoria, provvederà per i fatti suoi a rimuoverlo. Esistono metodi per forzare una garbage collection, ma normalmente non è necessario impiegarli (anzi, spesso è controproducente).
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Quote Originariamente inviata da MItaly Visualizza il messaggio
    Nel momento in cui non ci sono più riferimenti ad un certo oggetto raggiungibili dal tuo programma
    Ecco è questo che non mi entra in testa. Intanto il riferimento si intende alla struttura o all'oggetto istanziato mediante quella struttura? Cos'è per la precisione un "riferimento a SphHWorld"? Anche quando l'oggetto k di tipo SphHWorld viene eliminato, tutto il programma è costellato di riferimenti a questo oggetto e a questa struttura. Non mi è chiaro....si parla di riferimenti in esecuzione del programma o riferimenti possibili che sono presenti nel programma ma non eseguiti?
    Ultima modifica di escocat; 02-11-2013 a 19:40

  4. #4
    Quote Originariamente inviata da escocat Visualizza il messaggio
    Ecco è questo che non mi entra in testa. Intanto il riferimento si intende alla struttura o all'oggetto istanziato mediante quella struttura?
    Ovviamente all'oggetto; se un oggetto non è più raggiungibile allora si può eliminare, indipendentemente dal fatto che esistano altre variabili di quel tipo.
    Cos'è per la precisione un "riferimento a SphHWorld"?
    Qualunque variabile di un reference type (=qualunque variabile di tipo classe; sono esclusi i tipi primitivi e le struct, che invece sono dei "value type"). Se hai un minimo di dimestichezza con C o C++, tutte le variabili di tipi "by reference" sono in realtà dei puntatori; se nessun puntatore punta più ad una certa istanza, questa può essere eliminata (quando gli gira al garbage collector).
    Anche quando l'oggetto k di tipo SphHWorld viene eliminato, tutto il programma è costellato di riferimenti a questo oggetto e a questa struttura.
    Se ci sono altri riferimenti che puntano al medesimo oggetto, allora ovviamente non viene eliminato (dato che è ancora utilizzato altrove); se invece ci sono altre variabili di tipo SphHWorld che puntano ad altre istanze non ha alcuna rilevanza.
    Non mi è chiaro....si parla di riferimenti in esecuzione del programma o riferimenti possibili che sono presenti nel programma ma non eseguiti?
    Di riferimenti esistenti, cosa importa ai fini della cancellazione di una certa istanza che ci possono essere dei riferimenti ad altre istanze? Il garbage collector concettualmente fa una cosa molto semplice - se una certa istanza non è più utilizzata (=non c'è più nessuna variabile che punta ad essa) la elimina.

    In ogni caso, dovresti ripassarti un po' il tuo libro di C#, value type/reference type, GC e compagnia sono abbastanza i fondamentali del linguaggio...
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    MItaly intanto ti ringrazio per le tue risposte e mi scuso per la sciocchezza che ho detto: un nome di struttura non è un riferimento! Semmai lo è il nome dell'oggetto istanziato con quella struttura. Dunque il riferimento incriminato è la componente value dell'hashtable e tutto comincia esattamente qui:

    codice:
         //METODO CHE INIZIALIZZA IL SISTEMA
            public void InitSystem()
            {
                Planets.Add("A", new Star(...);    
    
                Planets.Add("B", new SphWorld(....);  
    
                ................ ecc.
     
          }
    
    
    Il riferimento è My.Planets[k]!
    Vediamo se ho capito: se non mi avvicino ad alcun pianeta la memoria è pervasa di oggetti SphWorld che non pesano molto. Supponiamo che lo spazio di memoria riservato all'oggetto k di hashtable sia 1000 K.
    Quando entro nell'Event-Horizon di un oggetto il suo riferimento non cambia, ma cambia il tipo dell'oggetto. Infatti nel Solve l'elemento k di hash viene prima rimosso e poi aggiunto con lo stesso indice k ma di tipo SphHWorld, ben più "pesante"

    codice:
    public static void Solve(string k)
            {
                My.Planets.Remove(k);
     
                My.Planets.Add(k, new SphHWorld(...);
     
           }
    
    Quindi a questo punto la memoria indirizzata dal "puntatore" My.Planets[k] viene "allargata" e riempita in abbondanza. Supponiamo che ora lo spazio di memoria riservato all'oggetto k sia 100000000 K.
    Questa situazione rimane finchè sorvolo o atterro su questo oggetto (pianeta). Quando lascio il pianeta, succede questo:

    codice:
    public static void Unsolve(string k)
            {
              My.Planets.Remove(k);
    
              My.Planets.Add(k, new SphWorld(...);
    
            }
    
    Il riferimento continua ad esistere perchè l'"indirizzo" My.Planets[k] non è stato modificato, è cambiato di nuovo solo il tipo della sua componente 'Value', e l'istanza è tornata ad essere "leggera". Dunque la memoria puntata da k esiste sempre, dall'inizio alla fine del programma.
    Mi chiedo: a questo punto lo spazio indirizzato da k è rimasto 100000000 K di cui solo 1000 K riempiti oppure 99999000 sono stati svuotati e resi disponibili per altre risorse? Grazie.
    Ultima modifica di escocat; 03-11-2013 a 10:24

  6. #6
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    la tua situazione è quella in cui hai due riferimenti ad un oggetto e ne disponi l'eliminazione attraverso uno dei due. L'oggetto non puo essere eliminato e non per via della GC ma perchè è ancora perfettamente lecito usarlo attraverso l'altro riferimento.

    Riducendo all'osso tu hai una cosa del genere:

    codice:
    class My {
      collection Planets;
    
      void H1(string key) {
        planet o = Planets[key];
        Solve(key);
        //o esiste o è stato eliminato? 
      }
    
      void Solve(string key) {
        Planets.Remove(key);
      }
    }
    Dopo il Solve puoi ancora utilizzare il pianeta attraverso la o. Non è stato eliminato e non lo sarà finche il riferimento o non perderà lo scope.

    Ecco cosa accade (mooolto teoricamente):
    1) Crei la collection di pianeti a livello di classe e fai partire il main (o il ciclo Update Draw nel tuo caso). Nello stack viene memorizzato un riferimento alla collection (Planets) e in memoria vengono istanziati, diciamo, 3 pianeti.
    2) Entri in H1 e nello stack memorizzi un ulteriore riferimento ad uno dei tre pianeti, diciamo il secondo. In questo momento il secondo pianeta è raggiungibile sia da questo riferimento sia dal riferimento all'intera collection.
    2a) Il Garbage collector ha bisogno di memoria e inizia ad analizzare lo stack. Trova Planets che punta ai tre pianeti in memoria e contrassegna quei tre pianeti come oggetti da non eliminare, poi trova o che punta al secondo pianeta e lo contrassegna come da non eliminare (inutile visto che l'ha fatto prima). Il GC ora comincia a scorrere la memoria per eliminare tutti gli oggetti non marcati ma non elimina nulla.
    3) Entri in Solve e viene comandata l'eliminazione del secondo pianeta. Planets ora punta ad una collection fatta di due pianeti il primo e il terzo mentre o punta al secondo pianeta.
    3a) Il GC necessita di memoria e ricomincia ad analizzare lo stack. Planets punta al primo e al terzo e i due pianeti vengono contrassegnati come oggetti da non eliminare. o punta al secondo e anche lui viene graziato. Ancora una volta scorrendo la memoria il GC non trova nulla da eliminare.
    4) Termina lo scope di Solve e si ritorna in H1. I pianeti sono intatti solo che attraverso la collection non puoi piu vedere il secondo pianeta che puoi comunque raggiungere attraverso il riferimento o.
    5) Termina H1 e quindi termina anche lo scope di 'o' il quale viene eliminato dallo stack.
    5a) Il GC ha bisogno di memoria e comincia ad analizzare lo stack. Trova Planets che punta al primo e al terzo e marca i due oggetti per non eliminarli. Non trova nientaltro nello stack. Ora va in memoria e comincia ad eliminare tutti gli oggetti che non sono stati marcati, trova il secondo pianeta e lo elimina.

    Questo fatto di tenere in vita un riferimento ad un oggetto che andrebbe eliminato, lungo una catena di chiamate è da evitare il piu possibile. Prima che per le performance la ragione principale è la consistenza dello stato del programma: Cosa ci fa in giro un pianeta nello stato di Near se il programma lo ha messo in stato di Far? Magari nel tuo caso non succede nulla ma in linea generale è (o sarà) un problema.
    Dal lato performance la cosa sicuramente crea delle ripercussioni. Se dopo il solve o l'unsolve hai bisogno di memoria, perche magari devi mettere in Near altri tot pianeti, non potrai contare su quella che si sarebbe liberata dai pianeti near contrassegnati come Far fino alla fine di H1 e cioè al prossimo giro.

    Quello che segue potrebbe stravolgere quanto detto fin'ora e per questo lo metto solo alla fine...
    E se il tipo shipworld è una struct e non un oggetto? (cosa che in xna accade poco è spesso).
    Qui le cose cambiano.
    Le struct non sono oggetti in memoria e non hanno riferimenti. le struct vengono copiate nello stack cosi come sono e vengono eliminate al termine dello scope.
    Le collection sono oggetti in memoria per cui Planets rimane cosi com'è (un array di pianeti in memoria anche se i pianeti sono struct), quello che cambia è la variabile o. o non è piu un riferimento al secondo pianeta memoria. o è una variabile nello stack dentro cui viene copiato tutto il contenuto del secondo pianeta.
    Nel punto 3a della timeline precedente il secondo pianeta viene eliminato perche 'o' non lo referenzia e quindi il GC non lo ha marcato per la 'sopravvivenza'.
    Questo risolverebbe il problema delle performance ma non risolve il primo e piu importante problema: che ci fa un o ancora in giro?

    Tutta questa pappina per arrivare alla conclusione:
    Evita questa situazione il piu possibile. quando devi modificare una collection usa la collection e non riferimenti agli oggetti dentro la collection. I riferimenti agli oggetti della collection andrebbero usati solo quando la collection non viene modificata magari quando un oggetto viene passato ad una funzione che non vede la collection intera (e quindi non puo modificaarla). In tutti gli altri casi usa direttamente il riferimento alla collection (planets[key]).

  7. #7
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Ecco cosa accade (mooolto teoricamente):
    1) Crei la collection di pianeti a livello di classe e fai partire il main (o il ciclo Update Draw nel tuo caso). Nello stack viene memorizzato un riferimento alla collection (Planets) e in memoria vengono istanziati, diciamo, 3 pianeti.
    E qui ci siamo.

    2) Entri in H1 e nello stack memorizzi un ulteriore riferimento ad uno dei tre pianeti, diciamo il secondo. In questo momento il secondo pianeta è raggiungibile sia da questo riferimento sia dal riferimento all'intera collection.
    OK. il secondo pianeta è l'oggetto di tipo SphWorld (leggero), raggiungibile con Planets["B"] e 'x'. Altri riferimenti: Planets["A"] e Planets["C"].

    2a) Il Garbage collector ha bisogno di memoria e inizia ad analizzare lo stack. Trova Planets che punta ai tre pianeti in memoria e contrassegna quei tre pianeti come oggetti da non eliminare, poi trova o che punta al secondo pianeta e lo contrassegna come da non eliminare (inutile visto che l'ha fatto prima). Il GC ora comincia a scorrere la memoria per eliminare tutti gli oggetti non marcati ma non elimina nulla.
    3) Entri in Solve e viene comandata l'eliminazione del secondo pianeta. Planets ora punta ad una collection fatta di due pianeti il primo e il terzo mentre o punta al secondo pianeta.
    OK. Sono sul pianeta "B".

    codice:
     
          public static void H1(string k, float FM, Vector3 L)
            {
                 if (My.Planets[k].GetType().ToString() == My.SphType)
    
               {
                    SphWorld x = (SphWorld)My.Planets[k];              Vector3 d = My.Discovery.Position - x.Location;
                    //costruisce la collection di profondità
                    double D = Math.Sqrt((Math.Pow(d.X, 2) + Math.Pow(d.Y, 2) + Math.Pow(d.Z, 2)));
                  My.Discovery.Depthlist.Add(-D, k);
    
                    ...
                  //Solving
                    if (d.Length() < x.Ehorizon)
                       SphHWorld.Solve(k); 'TRASFORMA x NEL TIPO 'SphHWorld'
                }
    
                else
    
                {
                    SphHWorld x = (SphHWorld)My.Planets[k];
                  Vector3 d = My.Discovery.Position - x.Location;
                    //costruisce la collection di profondità
                    double D = Math.Sqrt((Math.Pow(d.X, 2) + Math.Pow(d.Y, 2) + Math.Pow(d.Z, 2)));
                  My.Discovery.Depthlist.Add(-D, k);
                  ...
                  //Unsolving
                    if (d.Length() > x.Ehorizon)
                        SphHWorld.Unsolve(k);'RIPORTA x IN AL TIPO 'SphWorld'
                }
    
            }
    codice:
          public static void Solve(string k)
            {
    
                My.Planets.Remove(k);  
    
                My.Planets.Add(k, new SphHWorld(...);
    
          }
    RIFERIMENTI ATTIVI:
    Planets["A"] (Far = leggero).
    Planets["B"] (Near = pesante).
    Planets["C"] (Far)
    x (Far)

    3a) Il GC necessita di memoria e ricomincia ad analizzare lo stack. Planets punta al primo e al terzo e i due pianeti vengono contrassegnati come oggetti da non eliminare. o punta al secondo e anche lui viene graziato. Ancora una volta scorrendo la memoria il GC non trova nulla da eliminare.
    OK. Ma Planets[] punta anche a "B".

    4) Termina lo scope di Solve e si ritorna in H1. I pianeti sono intatti solo che attraverso la collection non puoi piu vedere il secondo pianeta che puoi comunque raggiungere attraverso il riferimento o.
    NO. La collection ha sempre tre pianeti. O sbaglio?

    5) Termina H1 e quindi termina anche lo scope di 'o' il quale viene eliminato dallo stack.
    OK. RIFERIMENTI ATTIVI:
    Planets["A"](Far)
    Planets["B"](Near)
    Planets["C"](Far)

    5a) Il GC ha bisogno di memoria e comincia ad analizzare lo stack. Trova Planets che punta al primo e al terzo e marca i due oggetti per non eliminarli. Non trova nientaltro nello stack. Ora va in memoria e comincia ad eliminare tutti gli oggetti che non sono stati marcati, trova il secondo pianeta e lo elimina.
    NO. "B" ESISTE. IO CI SONO SOPRA!.

    Questo fatto di tenere in vita un riferimento ad un oggetto che andrebbe eliminato, lungo una catena di chiamate è da evitare il piu possibile. Prima che per le performance la ragione principale è la consistenza dello stato del programma: Cosa ci fa in giro un pianeta nello stato di Near se il programma lo ha messo in stato di Far? Magari nel tuo caso non succede nulla ma in linea generale è (o sarà) un problema.
    Dal lato performance la cosa sicuramente crea delle ripercussioni. Se dopo il solve o l'unsolve hai bisogno di memoria, perche magari devi mettere in Near altri tot pianeti, non potrai contare su quella che si sarebbe liberata dai pianeti near contrassegnati come Far fino alla fine di H1 e cioè al prossimo giro.
    ??????????????????
    Forse non ho ben compreso ....
    Ultima modifica di escocat; 03-11-2013 a 12:14

  8. #8
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    ho usato un esempio ridotto al necessario per rispondere ai dubbi su come, se e quando veniva resa disponibile la memoria nel tuo programma. I passaggi devono riferirsi al mio codice (che non prevede il reinserimento del pianeta sotto altro tipo, cosa che avrebbe introdotto un elemento di complessità nella spiegazione). Capito quel codice e quel procedimento avresti trovato la risposta ai tuoi dubbi.

    Non rifarò tutti i passaggi da capo, ti correggo solo i punti in cui sbagli:

    RIFERIMENTI ATTIVI:
    Planets["A"] (Far = leggero).
    Planets["B"] (Near = pesante).
    Planets["C"] (Far)
    x (Far)
    quel Planets["B"] è un QUARTO pianeta. il fatto che abbia B come chiave non significa nulladal punto di vista della memoria, in memoria ci sono 4 pianeti distinti in quello stage. (il secondo puntato da x e che finche c'è x non puo essere eliminato dalla memoria).

    NO. "B" ESISTE. IO CI SONO SOPRA!.
    ecco appunto io ho detto secondo non B. B esiste ed è il quarto pianeta creato DOPO aver tolto il secondo dai riferimenti della collection. La GC (come ho detto) elimina il secondo, quello puntato da x e dopo che x è uscita dallo scope.
    Ora e solo dopo l'eliminazione del secondo pianeta sei a tre pianeti in memoria:
    A il primo
    B il quarto
    C il terzo.


    ??????????????????
    mi riferisco al fatto che c'è un momento in cui ci sono 4 pianeti accessibili e presenti in memoria e questo non va bene. Per risolvere basta evitare di usare variabili come la x e usare Planets[key] direttamente.

  9. #9
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    RIFERIMENTI ATTIVI:
    Planets["A"] (Far = leggero).
    Planets["B"] (Near = pesante).
    Planets["C"] (Far)
    x (Far)



    quel Planets["B"] è un QUARTO pianeta. il fatto che abbia B come chiave non significa nulladal punto di vista della memoria, in memoria ci sono 4 pianeti distinti in quello stage. (il secondo puntato da x e che finche c'è x non puo essere eliminato dalla memoria).
    mmmmmm....4° pianeta?
    Ho bisogno di chiarirmi le idee, e ti farei una statua per la tua santa pazienza.

    1) Ma se un hash ha 3 elementi e ne rimuovo uno, gli elementi dell'hash non si riducono a 2? L'hashtable non è una lista? Certe volte usiamo bene le cose ma non le capiamo a fondo....

    2) Se dall'hashtable rimuovo l'elemento k-esimo che aveva key "B" e aggiungo un elemento con key "B" più "pesante", cosa succede in memoria? Viene semplicemente "espansa" la stessa memoria indirizzata o si creano due aree di memoria diverse?

    Grazie.

  10. #10
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    la metafora dei palloncini e dei fili è funzionalissima.!!

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 © 2026 vBulletin Solutions, Inc. All rights reserved.