Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it L'avatar di XWolverineX
    Registrato dal
    Aug 2005
    residenza
    Prague
    Messaggi
    2,565

    C - Puntatore a char *

    salve.
    Mi stavo chiedendo, se io faccio
    codice:
    char *testo = "Ciao";
    Alla fine del programma, devo liberare la memoria che ha occupato?
    "Se proprio devono piratare, almeno piratino il nostro." (Bill Gates)

    "Non è possibile che 2 istituzioni statali mi mettano esami nello stesso giorno." (XWolverineX)

    http://xvincentx.netsons.org/programBlog

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254

    Re: C - Puntatore a char *

    Originariamente inviato da XWolverineX
    salve.
    Mi stavo chiedendo, se io faccio
    codice:
    char *testo = "Ciao";
    Alla fine del programma, devo liberare la memoria che ha occupato?
    No, perché quel "Ciao" è una stringa literal cioè una stringa costante che è conosciuta a tempo di compilazione. Il compilatore la posiziona in un segmento di dati (tipicamente read-only).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  3. #3
    Devi liberare la memoria solo se fai una malloc.

    Parlando di teoria molto spicciola, in un linguaggio di programmazione (C nel tuo caso) esistono due "tipologie" di memoria:

    1. Lo stack
    2. Lo heap

    Lo stack è la memoria che viene allocata ogni volta che richiami una funzione. Per esempio se ho un programma del genere:

    Codice PHP:
    int main(){
         
    x(3);
         
         return 
    0;
    }

    int x(int i){
        
    j(++i);
    }

    int j(int i){
        return;

    lo stack al momento della chiamata a j() nella funzione x() sarà:

    j() --> int i = 4;
    x() --> int i = 3;
    main()

    Ora ogni frame dello stack ha una zona di memoria che ti permette di memorizzare variabili locali e valori locali nel tuo caso

    char *str = "ciao";

    avresti avuto il frame main:

    main() --> char *str --> 'ciao'

    dove il valore del puntatore str sarebbe l'indirizzo di memoria interno al frame main dello stack.

    Ora ogni volta che una funziona ritorna, il frame viene distrutto e quindi la memoria viene rilasciata. Infatti nel tuo caso proprio per questo motivo non serve liberare la memoria occupata dalla stringa. In pratica quando il tuo programma termina o più precisamente quando il main ritorna la memorica occupata da *str viene automaticamente liberata perchè il frame main dello stack viene liberato.

    Qual'è il problema di questo meccanismo?
    Non puoi allocarti strutture globali, a meno che non le allochi nello stack del main con ovvi problemi di gestione per le funzioni superiori al main, e inoltre allocare grandi strutture nello stack non è un modo efficente di gestione delle risorse in quanto è meglio mantenere uno stack piccolo che permette di liberare facilmente le risorse locali e di ritornare velocemente al chiamante (la funzione che alloca un frame nello stack).
    Per questo motivo esiste lo Heap, una zona di memoria libera in cui allocare quello che si vuole in modo dinamico (nel senso che la memoria viene rilocata e assegnata al processo chiamante dal sistema operativo di volta in volta che se ne ha bisogno).

    In C per allocare memoria nello Heap usi la funzione malloc (o uno dei sui cugini) la quale non fa null' altro che chiedere al kernel del tuo sistema operativo di assegnare una specifica quantità di memoria per il processo chiamante: infatti ti ritorna un puntatore a void che non significa puntatore a nulla, ma puntatore a memoria generalizzata.
    In Java che è un linguaggio più evoluto del C si usa l' operatore new che serve a creare un oggetto. La JVM in automatico e nascosto ai nostri occhi farà una malloc per allocare la giusta dimensione della struttura da noi creata.

    Il problema che sorge nell' uso di questa memoria è la frammentazione e l' uso sconsiderato che se ne può fare, cioè il dimenticarsi di liberare la memoria. In C esiste la funzione free(void *ptr) che non fa nientaltro che dire al Sistema operativo che la memoria allocata dall' indirizzo puntato da *ptr può essere riassegnata per un altro processo o sempre per lo stesso processo in una futura chiamata malloc.
    In Java o comunque in tutti i linguaggi più moderni C# per esempio, è stata tolta la possibiltà al programmatore di liberare la memoria e si è introdotto un sistema automatico di liberazione della mamoria chiamato garbage collection. La garbage collection è una funzionalità, simile ad un crontab, di un linguaggio che si occupa di liberare autonomamente la memoria non più utilizzata utilizzando particolari algoritmi il più diffuso è il "mark and sweep".
    I linguaggi moderni tolgono la possibilità di liberare la memoria manualmente per svariati motivi:
    1. Per rendere il linguaggio più semplice.
    2. Per rendere i programmi scritti in quel linguaggio più sicuri, perchè è cattiva norma di quasi tutti i programmatorii dimenticarsi da qualche parte del codice una free, il che è sintomo di cattiva programmazione e soprattutto tende a rendere programmi complessi insicuri
    3. Rendere la programmazione più snella

    Il problema del garbage collection è che poi i nostri programmi saranno più lenti. Vedi programmi scritti in Java.

    Spero di essere stato abbastanza esaustivo.
    Ciao

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,466
    In tutto questo discorso, non so se ho capito un punto ...

    Intendi dire che la stringa "ciao" del nostro esempio e' allocata nello stack?

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Originariamente inviato da oregon
    In tutto questo discorso, non so se ho capito un punto ...

    Intendi dire che la stringa "ciao" del nostro esempio e' allocata nello stack?
    Nessun compilatore sarebbe così stupido da allocare i caratteri di una stringa literal sullo stack.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  6. #6
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,466
    Sicuramente ... ma dato che quello che si capiva dal discorso precedente era proprio questo, volevo sapere se avevo capito male io ... ... o Markosky non e' stato preciso ...

  7. #7
    Originariamente inviato da oregon
    puntatore chIn tutto questo discorso, non so se ho capito un punto ...

    Intendi dire che la stringa "ciao" del nostro esempio e' allocata nello stack?
    In effetti non sono stato preciso in quanto ho detto che "ciao" sta nel frame del main. Ovviemente è sbagliato, "ciao" è un valore costante che verrà messo nel segmento dati dal compilatore al momento della compilazione.

    Rimane il fatto che il puntatore *testo rimane nello stack.
    Quindi nello stack avrai memorizzato l'indirizzo di memoria del segmento dati dove è memorizzato "ciao0", in quanto altrimenti il compilatore non riuscirebbe a gestire lo scope di quella variabile.

  8. #8
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,466
    Originariamente inviato da Marcoski
    In effetti non sono stato preciso in quanto ho detto che "ciao" sta nel frame del main. Ovviemente è sbagliato, "ciao" è un valore costante che verrà messo nel segmento dati dal compilatore al momento della compilazione.

    Rimane il fatto che il puntatore *testo rimane nello stack.
    Quindi nello stack avrai memorizzato l'indirizzo di memoria del segmento dati dove è memorizzato "ciao0", in quanto altrimenti il compilatore non riuscirebbe a gestire lo scope di quella variabile.
    Ecco ... questo era esattamente quello che intendevo ...

  9. #9
    Utente di HTML.it L'avatar di XWolverineX
    Registrato dal
    Aug 2005
    residenza
    Prague
    Messaggi
    2,565
    Grazie per la delucidazione.
    Il fatto che fosse un puntatore mi dava certi dubbi.
    Credevo che alla fine del blocco fosse liberato il puntatore, ma non quello a cui punta.

    Inoltre mi stavo anche chiedendo perchè

    codice:
    char *c = "Ciao"; // Ok
    int *i = 10; //No
    Ci ho riflettuto è credo che sia perchè
    "Ciao"; è proprio un const char *
    mentre 10 è un int e non un int *
    Giusto?
    "Se proprio devono piratare, almeno piratino il nostro." (Bill Gates)

    "Non è possibile che 2 istituzioni statali mi mettano esami nello stesso giorno." (XWolverineX)

    http://xvincentx.netsons.org/programBlog

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Originariamente inviato da XWolverineX
    Inoltre mi stavo anche chiedendo perchè

    codice:
    char *c = "Ciao"; // Ok
    int *i = 10; //No
    Ci ho riflettuto è credo che sia perchè
    "Ciao"; è proprio un const char *
    mentre 10 è un int e non un int *
    Giusto?
    Qui c'è da fare attenzione:

    char *c = "Ciao";
    significa assegnare alla variabile 'c' (puntatore a char) l'indirizzo del primo carattere della stringa literal. E questo è ok.

    int *i = 10;
    significa assegnare alla variabile 'i' (puntatore a int) l'indirizzo 10!!
    A parte il fatto che se proprio si volesse fare una cosa del genere, si dovrebbe mettere un cast esplicito:
    int *i = (int*) 10;

    infatti 10 viene valutato come valore intero, non come un indirizzo.
    Ma comunque, quasi sicuramente, non sarebbe corretto lo stesso. Nei moderni sistemi operativi, l'indirizzo 10 non è di certo una locazione accessibile!!
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

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.