Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 16
  1. #1
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412

    Le variabili locali vengono cancellate dopo l'esecuzione della funzione?

    Salve vorrei capire in linea generale (senza quindi parlare di un particolare linguaggio di programmazione), le variabili locali, ovvero dichiarate all'interno delle funzioni, vengono automaticamente cancellate all'uscita della funzione? Quindi parlando di spazio occupato in memoria, si può tranquillamente dire che una variabile globale resta in memoria (occupando quindi spazio) per tutta la durata del programma, a differenza di quelle locali che invece vengono auto-eliminate (garbage collected?).
    Se si, in linea di massima un programma ottimizzato dovrebbe avere quanto meno variabili globali possibili?

    Inoltre se le variabili locali vengono eliminate, perchè in alcuni casi (a meno che non vado errato) è possibile ugualmente accedervi dall'esterno? Vuol dire che restano in memoria...

  2. #2
    Difficile fare un discorso generale, dato che è una questione non semplicissima e ogni linguaggio potenzialmente può fare a modo suo, e la semantica delle variabili (per valore, per riferimento), i metodi di allocazione (stack, heap) e deallocazione (manuale, RAII, reference counting, garbage collection) differiscono.

    In generale il discorso può essere abbastanza vero, ma molto cambia a seconda del linguaggio.

    In genere nei linguaggi compilati e con semantica di variabili "per valore" (ad esempio C e C++) le variabili locali sono "logicamente" cancellate (vengono richiamati i distruttori e non vi si può più accedere "legalmente"), ma di fatto lo spazio di memoria usato per le variabili locali (e non solo) è sempre lo stesso (lo stack), che viene allocato all'avvio del programma e deallocato alla fine. Trattandosi di spazio limitato (e che generalmente non può crescere, anche se ci sono delle eccezioni) normalmente va usato con una certa parsimonia.

    Ergo: nel caso in cui la variabile stia effettivamente sullo stack, in termini di memoria consumata non cambia niente all'uscita della funzione.

    Per i linguaggi dove la maggior parte delle variabili sono in realtà dei riferimenti ad oggetti allocati nell'heap (Java, .NET, Python, ...) la questione è diversa: tutti gli oggetti sono allocati nell'heap, e sullo stack (che di base funziona in maniera simile) ci sono solo puntatori. Tuttavia, a differenza dei puntatori in linguaggi non gestiti, la distruzione di una variabile locale fa sì che l'oggetto a cui punta sia "distruttibile": nei linguaggi con reference counting (ad esempio VB6 o Python) al momento della distruzione della variabile il reference counter viene decrementato, e se raggiunge lo zero l'oggetto a cui punta la variabile viene distrutto; nei linguaggi con garbage collection, invece, non viene fatto nulla di particolare oltre che distruggere la variabile situata sullo stack. Sarà il garbage collector, quando decide che è il momento di fare pulizia, a verificare che l'oggetto a cui puntava la variabile non è più raggiungibile dal programma, e quindi ad eliminarlo.
    In questi casi, quindi, lo stack è (in genere) sostanzialmente statico come dimensioni (se aumenta/diminuisce di dimensioni, comunque, lo fa a grossi blocchi), ma gli oggetti veri e propri stanno sull'heap, e vengono distrutti automaticamente quando non servono più (anche se non necessariamente questo accade immediatamente).

    ---

    Sui globali, al di là dell'ottimizzazione (che in genere è rilevante fino ad un certo punto), ci sono questioni di ordine logico ben più rilevanti: il vero problema delle variabili globali è che sono accessibili da tutto il programma, per cui può essere complesso seguire come il suo stato cambia; in un certo senso, le variabili globali "accoppiano" parti di codice scorrelate, rendendo più complesso capirne il funzionamento (oltre che il debugging).
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    purtroppo la domanda un minimo va contesualizzata. Comunque questo

    (garbage collected?).
    non centra nulla con le variabili. Operazioni di Garbage collection riguardano l'heap e puliscono le zone di memoria riservate da operazioni di allocazione. In C allochi la memoria con malloc e usi il puntatore p per accedervi, quando quella zona di memoria non ti serve piu devi fare free(p). p è la variabile che semplicemente punta alla zona di memoria. In ambienti con il garbage collector le operazioni di free sono nascoste ma non riguardano le variabili bensi le rispettive zone di memoria allocate.

    Per quanto riguarda le variabili in senso stretto queste vivono sempre e solo nello stack, durano per tutta la durata del loro scope e non è possibile accedervi o recuperarle dopo lo scope in quanto vengono semplicemente eliminate. Nell' esempio precedente la variabile p che vive nello stack verra eliminata alla fine dello scope ma non centra nulla con l'operazione di free.

    Se si, in linea di massima un programma ottimizzato dovrebbe avere quanto meno variabili globali possibili?
    no. Lo stack lo puoi riempire tutto in una volta all'inizio dichiarando tutte le variabili che ti servono per tutto il programma una sola volta globalmente. Se ci stanno, cosa molto probabile, il programma sarà certamente piu ottimizzato poichè si eviteranno tutti i passaggi parametri, le copie dei valori di ritorno, ecc. Ovviamente nessuno scrive programmi cosi (almeno non dopo il biennio dell'itis) perchè in programmazione l'ottimizzazione è tra le ultime cose che contano.

    L'ultima domanda non l'ho capita. Credo che forse dovrai specificare almeno il linguaggio/ambiente a cui ti riferisci.

  4. #4
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    MItaly mi sento un novizio con una risposta sotto la tua, ora sono costretto a leggerla per vedere se ho scritto qualche cazzata

  5. #5
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412
    Originariamente inviato da MItaly


    ---

    Sui globali, al di là dell'ottimizzazione (che in genere è rilevante fino ad un certo punto), ci sono questioni di ordine logico ben più rilevanti: il vero problema delle variabili globali è che sono accessibili da tutto il programma, per cui può essere complesso seguire come il suo stato cambia; in un certo senso, le variabili globali "accoppiano" parti di codice scorrelate, rendendo più complesso capirne il funzionamento (oltre che il debugging).
    prima devo documentarmi sull'heap e sullo stack, nel frattempo chiedo, a proposito dell'ultimo periodo del post.. Facciamo che ho un programma con diverse funzioni, ciascuna delle quali necessita di far riferimento ad una medesima variabile... Ad esempio, all'inizio del programma l'utente deve inserire il suo nome, parametro che mi torna utile in più passaggi del programma.. E' necessario o no memorizzarlo in una variabile globale?

  6. #6
    Nella maggior parte dei linguaggi non è strettamente necessario, può essere sufficiente semplicemente passarlo sempre come parametro, o metterlo in un campo della classe i cui metodi devono lavorare con il dato in questione... ma se effettivamente serve ovunque può aver senso fare una variabile globale, visto che continuare a passare in giro sempre lo stesso dato è inutilmente ripetitivo.

    Ribadisco comunque che (1) in genere l'ottimizzazione con queste robe c'entra relativamente poco e (2) se non circostanziamo su un linguaggio preciso stiamo parlando di aria fritta...
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412
    Originariamente inviato da MItaly
    Nella maggior parte dei linguaggi non è strettamente necessario, può essere sufficiente semplicemente passarlo sempre come parametro, o metterlo in un campo della classe i cui metodi devono lavorare con il dato in questione... ma se effettivamente serve ovunque può aver senso fare una variabile globale, visto che continuare a passare in giro sempre lo stesso dato è inutilmente ripetitivo.

    Ribadisco comunque che (1) in genere l'ottimizzazione con queste robe c'entra relativamente poco e (2) se non circostanziamo su un linguaggio preciso stiamo parlando di aria fritta...
    uhm.. però mi pare di capire che prendi in considerazione una struttura ad oggetti.. Prendiamo invece un software semplice scritto in maniera procedurale.. C'è da considerare che la chiamata alle funzioni non avviene sempre in maniera continua, quindi se inizializzo una variabile nella funzione A, come faccio a ritrovarmela nella funzione Z considerando che tra A e Z, anche considerando le chiamate intermedie, non c'è una relazione?

    Cmq se tu dici che questa cosa non c'entra nulla con l'ottimizzazione, ma serve unicamente per creare codici più leggibili e intuitivi, allora il problema non si pone (la mia paura è sempre quella che, a causa della mia niubbaggine, crea algoritmi troppo "pacchiani" e che seppur funzionanti, funzionano male)..
    D'altra parte se un codice lo scrivo io e si suppone che nessun altro debba averci a che fare, che senso ha renderlo intuitivo?

  8. #8
    Originariamente inviato da American
    uhm.. però mi pare di capire che prendi in considerazione una struttura ad oggetti.. Prendiamo invece un software semplice scritto in maniera procedurale.. C'è da considerare che la chiamata alle funzioni non avviene sempre in maniera continua, quindi se inizializzo una variabile nella funzione A, come faccio a ritrovarmela nella funzione Z considerando che tra A e Z, anche considerando le chiamate intermedie, non c'è una relazione?
    Se vuoi che la variabile arrivi alla funzione Z in qualche maniera la devi far passare, il che significa che tutte le chiamate fino ad arrivare a Z si devono tirare dietro il dato in questione come argomento.
    Cmq se tu dici che questa cosa non c'entra nulla con l'ottimizzazione, ma serve unicamente per creare codici più leggibili e intuitivi, allora il problema non si pone (la mia paura è sempre quella che, a causa della mia niubbaggine, crea algoritmi troppo "pacchiani" e che seppur funzionanti, funzionano male)..
    Dal punto di vista dell'efficienza, queste sono micro-ottimizzazioni, da considerare solo se le cose vanno davvero male e se effettivamente si vede tramite profiling che c'è un guadagno di qualche genere a cambiare un approccio con l'altro, piuttosto è importante (1) scrivere un programma che funzioni correttamente (anche nei "casi limite") e (2) partire usando gli algoritmi corretti e più adatti (macro-ottimizzazione). L'uso o meno di variabili globali e compagnia è invece fondamentale dal punto di vista della mantenibilità del codice.
    D'altra parte se un codice lo scrivo io e si suppone che nessun altro debba averci a che fare, che senso ha renderlo intuitivo?
    1. Se riprendi in mano il tuo codice tra tre (o peggio ancora, sei o dodici) mesi e nel frattempo hai fatto altro, stai tranquillo che non ti ricordi più perfettamente come è fatto, e se l'hai scritto in maniera incasinata c'è da ridere.
    2. Non è questione di scrivere codice "intuitivo", ma mantenibile, ovvero che in caso di bachi è facile rintracciare dove possa esserci il problema, se voglio aggiungere una funzione non devo stravolgere tutta la struttura del programma, modificare un certo parametro non richieda di dover cambiare qualcosa in centomila punti diversi, eccetera. È per questo motivo che, anche in un progetto in cui si lavora da soli, è fondamentale essere "disciplinati" e costruire una struttura ordinata, ben comprensibile (ricordarsi i commenti!), in cui i compiti del codice sono ben suddivisi e i vari moduli interagiscono in maniera chiara esattamente nei modi previsti.
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,590
    Per quanto riguarda la programmazione ad oggetti in ogni caso una chiamata del tipo
    codice:
    obj.fun(a1, a2...an)
    può essere resa in un linguaggio non ad oggetti come
    codice:
    fun(obj, a1, a2...an)
    assumendo che obj sia passato per riferimento e non per valore. Quindi puoi utilizzare gli stessi meccanismi della programmazione ad oggetti in un linguaggio procedurale.
    Dopotutto anche Python fa così
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  10. #10
    Utente di HTML.it
    Registrato dal
    Nov 2002
    Messaggi
    412
    ah allora indirettamente già programmo ad oggetti in quanto faccio sempre uso di funzioni..

    Cmq nella programmazione ad oggetti, e più precisamente nella creazione delle classi, le variabili vengono spesso dichiarate come public o private.
    Mi sono sempre chiesto quale sia il senso dato che pure mettendole public, è pur sempre lo sviluppatore a potervi accedervi, l'utente finale insomma, non rischia di combinare casini modificando una variabile in teoria privata.
    A questo punto i dubbi sono due:
    In questo caso c'è un ottimizzazione sull'uso della memoria?
    e se no, si torna al discorso che queste clausole sono delle "marche" per il programmatore per meglio ricordare il funzionamento del codice?

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