Comprensione codice con malloc() ecc..

di il
7 risposte

Comprensione codice con malloc() ecc..

Salve a tutti, dopo il problema risolto di ieri devo capire un nuovo codice e capire perchè da un certo output. Il problema è che a me sembra solo di vedere numeri a casaccio in questo output, non riesco a stabilire il criterio con cui malloc() realloc() e free() sortiscono certi effetti sui valori.
Il codice è questo:
#include<stdlib.h>
#include<stdio.h>

/*** Just playing with the malloc(), realloc(), free()
 *** system calls in order to guess how memory management
 *** is implemented on this machine. If you get SEGMENTATION
 *** FAULT while addressing unallocated heap memory, just run
 *** the program with different "min" and/or "max" values,
 *** explicitly given on the command line through argv[] ***/
int main(int argc, char**argv){
    unsigned char *p, *q, *oldp;
    int sz=1, min=-8, max=60;

    if ( argc > 1 )
        sscanf(argv[1],"%d",&sz);
    if ( sz <= 0 )
        sz = 1;
    else if ( sz > 300 )
        sz = 300;
    if ( argc > 2 )
        sscanf(argv[2],"%d",&min);
    if ( min > -1 )
        min = -1;
    else if ( min < -50 )
        min = -50;
    if ( argc > 3 )
        sscanf(argv[3],"%d",&max);
    if ( max < sz )
        max = sz;
    else if ( max > (sz+100) )
        max = sz+100;
    printf("... allocating %d unsigned chars, min=%d, max=%d\n\n",sz,min,max);
    p = (unsigned char*)malloc(sz);
    if ( p == NULL ) {
        printf("could not allocate p\n");
        exit(0);
      }
    printf("*p=%hhu\n",*p);
    { int i;
      for ( i = -1 ; i >= min ; i-- )
        printf("p[%d]=%hhu\n",i,p[i]);
      for ( i = 1 ; i <= max ; i++ )
        printf("p[%d]=%hhu\n",i,p[i]);
    }
    printf("\n... allocating %d more unsigned chars to a different pointer\n\n",sz);
    q = (unsigned char*)malloc(sz);
    if ( q == NULL ) {
        printf("could not allocate q\n");
        exit(0);
      }
    { int i;
      for ( i = -1 ; i >= min ; i-- )
        printf("q[%d]=%hhu\n",i,q[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("q[%d]=%hhu\n",i,q[i]);
    }
    { int i;
      for ( i = -1 ; i >= min ; i-- )
        printf("p[%d]=%hhu\n",i,p[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("p[%d]=%hhu\n",i,p[i]);
    }
    sz += 10;
    printf("\n... reallocating %d unsigned chars\n\n",sz);
    oldp = p;
    p = (unsigned char*)realloc((void*)p,sz);
    { int i;
      for ( i = -1 ; i >= min ; i-- )
        printf("p[%d]=%hhu\n",i,p[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("p[%d]=%hhu\n",i,p[i]);
      for ( i = -1 ; i >= min ; i-- )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
    }
    sz += 15;
    printf("\n... reallocating %d unsigned chars\n\n",sz);
    p = (unsigned char*)realloc((void*)p,sz);
    { int i;
      for ( i = -1 ; i >= min ; i-- )
        printf("p[%d]=%hhu\n",i,p[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("p[%d]=%hhu\n",i,p[i]);
      for ( i = -1 ; i >= min ; i-- )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
    }
    sz -= 25;
    printf("\n... reallocating %d unsigned chars\n\n",sz);
    p = (unsigned char*)realloc((void*)p,sz);
    { int i;
      for ( i = -1 ; i >= min ; i-- )
        printf("p[%d]=%hhu\n",i,p[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("p[%d]=%hhu\n",i,p[i]);
      for ( i = -1 ; i >= min ; i-- )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
    }
    printf("\n... freeing p\n\n",sz);
    free((void*)p);
    { int i;
      for ( i = 0 ; i >= min ; i-- )
        printf("p[%d]=%hhu\n",i,p[i]);
    }
    printf("\n... freeing q\n\n",sz);
    free((void*)q);
    { int i;
      for ( i = 0 ; i >= min ; i-- )
        printf("q[%d]=%hhu\n",i,q[i]);
      for ( i = -1 ; i >= min ; i-- )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
    }
    printf("\n... freeing oldp\n\n",sz);
    free((void*)oldp);
    { int i;
      for ( i = -1 ; i >= min ; i-- )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
      for ( i = 0 ; i <= max ; i++ )
        printf("oldp[%d]=%hhu\n",i,oldp[i]);
    }
    exit(0);
}
L'output questo:
... allocating 1 unsigned chars, min=-8, max=60

*p=0
p[-1]=0
p[-2]=0
p[-3]=0
p[-4]=0
p[-5]=0
p[-6]=0
p[-7]=0
p[-8]=33
p[1]=0
p[2]=0
p[3]=0
p[4]=0
p[5]=0
p[6]=0
p[7]=0
p[8]=0
p[9]=0
p[10]=0
p[11]=0
p[12]=0
p[13]=0
p[14]=0
p[15]=0
p[16]=0
p[17]=0
p[18]=0
p[19]=0
p[20]=0
p[21]=0
p[22]=0
p[23]=0
p[24]=225
p[25]=15
p[26]=2
p[27]=0
p[28]=0
p[29]=0
p[30]=0
p[31]=0
p[32]=0
p[33]=0
p[34]=0
p[35]=0
p[36]=0
p[37]=0
p[38]=0
p[39]=0
p[40]=0
p[41]=0
p[42]=0
p[43]=0
p[44]=0
p[45]=0
p[46]=0
p[47]=0
p[48]=0
p[49]=0
p[50]=0
p[51]=0
p[52]=0
p[53]=0
p[54]=0
p[55]=0
p[56]=0
p[57]=0
p[58]=0
p[59]=0
p[60]=0

... allocating 1 more unsigned chars to a different pointer

q[-1]=0
q[-2]=0
q[-3]=0
q[-4]=0
q[-5]=0
q[-6]=0
q[-7]=0
q[-8]=33
q[0]=0
q[1]=0
q[2]=0
q[3]=0
q[4]=0
q[5]=0
q[6]=0
q[7]=0
q[8]=0
q[9]=0
q[10]=0
q[11]=0
q[12]=0
q[13]=0
q[14]=0
q[15]=0
q[16]=0
q[17]=0
q[18]=0
q[19]=0
q[20]=0
q[21]=0
q[22]=0
q[23]=0
q[24]=193
q[25]=15
q[26]=2
q[27]=0
q[28]=0
q[29]=0
q[30]=0
q[31]=0
q[32]=0
q[33]=0
q[34]=0
q[35]=0
q[36]=0
q[37]=0
q[38]=0
q[39]=0
q[40]=0
q[41]=0
q[42]=0
q[43]=0
q[44]=0
q[45]=0
q[46]=0
q[47]=0
q[48]=0
q[49]=0
q[50]=0
q[51]=0
q[52]=0
q[53]=0
q[54]=0
q[55]=0
q[56]=0
q[57]=0
q[58]=0
q[59]=0
q[60]=0
p[-1]=0
p[-2]=0
p[-3]=0
p[-4]=0
p[-5]=0
p[-6]=0
p[-7]=0
p[-8]=33
p[0]=0
p[1]=0
p[2]=0
p[3]=0
p[4]=0
p[5]=0
p[6]=0
p[7]=0
p[8]=0
p[9]=0
p[10]=0
p[11]=0
p[12]=0
p[13]=0
p[14]=0
p[15]=0
p[16]=0
p[17]=0
p[18]=0
p[19]=0
p[20]=0
p[21]=0
p[22]=0
p[23]=0
p[24]=33
p[25]=0
p[26]=0
p[27]=0
p[28]=0
p[29]=0
p[30]=0
p[31]=0
p[32]=0
p[33]=0
p[34]=0
p[35]=0
p[36]=0
p[37]=0
p[38]=0
p[39]=0
p[40]=0
p[41]=0
p[42]=0
p[43]=0
p[44]=0
p[45]=0
p[46]=0
p[47]=0
p[48]=0
p[49]=0
p[50]=0
p[51]=0
p[52]=0
p[53]=0
p[54]=0
p[55]=0
p[56]=193
p[57]=15
p[58]=2
p[59]=0
p[60]=0

... reallocating 11 unsigned chars

p[-1]=0
p[-2]=0
p[-3]=0
p[-4]=0
p[-5]=0
p[-6]=0
p[-7]=0
p[-8]=33
p[0]=0
p[1]=0
p[2]=0
p[3]=0
p[4]=0
p[5]=0
p[6]=0
p[7]=0
p[8]=0
p[9]=0
p[10]=0
p[11]=0
p[12]=0
p[13]=0
p[14]=0
p[15]=0
p[16]=0
p[17]=0
p[18]=0
p[19]=0
p[20]=0
p[21]=0
p[22]=0
p[23]=0
p[24]=33
p[25]=0
p[26]=0
p[27]=0
p[28]=0
p[29]=0
p[30]=0
p[31]=0
p[32]=0
p[33]=0
p[34]=0
p[35]=0
p[36]=0
p[37]=0
p[38]=0
p[39]=0
p[40]=0
p[41]=0
p[42]=0
p[43]=0
p[44]=0
p[45]=0
p[46]=0
p[47]=0
p[48]=0
p[49]=0
p[50]=0
p[51]=0
p[52]=0
p[53]=0
p[54]=0
p[55]=0
p[56]=193
p[57]=15
p[58]=2
p[59]=0
p[60]=0
oldp[-1]=0
oldp[-2]=0
oldp[-3]=0
oldp[-4]=0
oldp[-5]=0
oldp[-6]=0
oldp[-7]=0
oldp[-8]=33
oldp[0]=0
oldp[1]=0
oldp[2]=0
oldp[3]=0
oldp[4]=0
oldp[5]=0
oldp[6]=0
oldp[7]=0
oldp[8]=0
oldp[9]=0
oldp[10]=0
oldp[11]=0
oldp[12]=0
oldp[13]=0
oldp[14]=0
oldp[15]=0
oldp[16]=0
oldp[17]=0
oldp[18]=0
oldp[19]=0
oldp[20]=0
oldp[21]=0
oldp[22]=0
oldp[23]=0
oldp[24]=33
oldp[25]=0
oldp[26]=0
oldp[27]=0
oldp[28]=0
oldp[29]=0
oldp[30]=0
oldp[31]=0
oldp[32]=0
oldp[33]=0
oldp[34]=0
oldp[35]=0
oldp[36]=0
oldp[37]=0
oldp[38]=0
oldp[39]=0
oldp[40]=0
oldp[41]=0
oldp[42]=0
oldp[43]=0
oldp[44]=0
oldp[45]=0
oldp[46]=0
oldp[47]=0
oldp[48]=0
oldp[49]=0
oldp[50]=0
oldp[51]=0
oldp[52]=0
oldp[53]=0
oldp[54]=0
oldp[55]=0
oldp[56]=193
oldp[57]=15
oldp[58]=2
oldp[59]=0
oldp[60]=0

... reallocating 26 unsigned chars

p[-1]=0
p[-2]=0
p[-3]=0
p[-4]=0
p[-5]=0
p[-6]=0
p[-7]=0
p[-8]=49
p[0]=0
p[1]=0
p[2]=0
p[3]=0
p[4]=0
p[5]=0
p[6]=0
p[7]=0
p[8]=0
p[9]=0
p[10]=0
p[11]=0
p[12]=0
p[13]=0
p[14]=0
p[15]=0
p[16]=0
p[17]=0
p[18]=0
p[19]=0
p[20]=0
p[21]=0
p[22]=0
p[23]=0
p[24]=0
p[25]=0
p[26]=0
p[27]=0
p[28]=0
p[29]=0
p[30]=0
p[31]=0
p[32]=0
p[33]=0
p[34]=0
p[35]=0
p[36]=0
p[37]=0
p[38]=0
p[39]=0
p[40]=145
p[41]=15
p[42]=2
p[43]=0
p[44]=0
p[45]=0
p[46]=0
p[47]=0
p[48]=0
p[49]=0
p[50]=0
p[51]=0
p[52]=0
p[53]=0
p[54]=0
p[55]=0
p[56]=0
p[57]=0
p[58]=0
p[59]=0
p[60]=0
oldp[-1]=0
oldp[-2]=0
oldp[-3]=0
oldp[-4]=0
oldp[-5]=0
oldp[-6]=0
oldp[-7]=0
oldp[-8]=33
oldp[0]=0
oldp[1]=0
oldp[2]=0
oldp[3]=0
oldp[4]=0
oldp[5]=0
oldp[6]=0
oldp[7]=0
oldp[8]=0
oldp[9]=0
oldp[10]=0
oldp[11]=0
oldp[12]=0
oldp[13]=0
oldp[14]=0
oldp[15]=0
oldp[16]=0
oldp[17]=0
oldp[18]=0
oldp[19]=0
oldp[20]=0
oldp[21]=0
oldp[22]=0
oldp[23]=0
oldp[24]=33
oldp[25]=0
oldp[26]=0
oldp[27]=0
oldp[28]=0
oldp[29]=0
oldp[30]=0
oldp[31]=0
oldp[32]=0
oldp[33]=0
oldp[34]=0
oldp[35]=0
oldp[36]=0
oldp[37]=0
oldp[38]=0
oldp[39]=0
oldp[40]=0
oldp[41]=0
oldp[42]=0
oldp[43]=0
oldp[44]=0
oldp[45]=0
oldp[46]=0
oldp[47]=0
oldp[48]=0
oldp[49]=0
oldp[50]=0
oldp[51]=0
oldp[52]=0
oldp[53]=0
oldp[54]=0
oldp[55]=0
oldp[56]=49
oldp[57]=0
oldp[58]=0
oldp[59]=0
oldp[60]=0

... reallocating 1 unsigned chars

p[-1]=0
p[-2]=0
p[-3]=0
p[-4]=0
p[-5]=0
p[-6]=0
p[-7]=0
p[-8]=49
p[0]=0
p[1]=0
p[2]=0
p[3]=0
p[4]=0
p[5]=0
p[6]=0
p[7]=0
p[8]=0
p[9]=0
p[10]=0
p[11]=0
p[12]=0
p[13]=0
p[14]=0
p[15]=0
p[16]=0
p[17]=0
p[18]=0
p[19]=0
p[20]=0
p[21]=0
p[22]=0
p[23]=0
p[24]=0
p[25]=0
p[26]=0
p[27]=0
p[28]=0
p[29]=0
p[30]=0
p[31]=0
p[32]=0
p[33]=0
p[34]=0
p[35]=0
p[36]=0
p[37]=0
p[38]=0
p[39]=0
p[40]=145
p[41]=15
p[42]=2
p[43]=0
p[44]=0
p[45]=0
p[46]=0
p[47]=0
p[48]=0
p[49]=0
p[50]=0
p[51]=0
p[52]=0
p[53]=0
p[54]=0
p[55]=0
p[56]=0
p[57]=0
p[58]=0
p[59]=0
p[60]=0
oldp[-1]=0
oldp[-2]=0
oldp[-3]=0
oldp[-4]=0
oldp[-5]=0
oldp[-6]=0
oldp[-7]=0
oldp[-8]=33
oldp[0]=0
oldp[1]=0
oldp[2]=0
oldp[3]=0
oldp[4]=0
oldp[5]=0
oldp[6]=0
oldp[7]=0
oldp[8]=0
oldp[9]=0
oldp[10]=0
oldp[11]=0
oldp[12]=0
oldp[13]=0
oldp[14]=0
oldp[15]=0
oldp[16]=0
oldp[17]=0
oldp[18]=0
oldp[19]=0
oldp[20]=0
oldp[21]=0
oldp[22]=0
oldp[23]=0
oldp[24]=33
oldp[25]=0
oldp[26]=0
oldp[27]=0
oldp[28]=0
oldp[29]=0
oldp[30]=0
oldp[31]=0
oldp[32]=0
oldp[33]=0
oldp[34]=0
oldp[35]=0
oldp[36]=0
oldp[37]=0
oldp[38]=0
oldp[39]=0
oldp[40]=0
oldp[41]=0
oldp[42]=0
oldp[43]=0
oldp[44]=0
oldp[45]=0
oldp[46]=0
oldp[47]=0
oldp[48]=0
oldp[49]=0
oldp[50]=0
oldp[51]=0
oldp[52]=0
oldp[53]=0
oldp[54]=0
oldp[55]=0
oldp[56]=49
oldp[57]=0
oldp[58]=0
oldp[59]=0
oldp[60]=0

... freeing p

p[0]=0
p[-1]=0
p[-2]=0
p[-3]=0
p[-4]=0
p[-5]=0
p[-6]=0
p[-7]=0
p[-8]=49

... freeing q

q[0]=0
q[-1]=0
q[-2]=0
q[-3]=0
q[-4]=0
q[-5]=0
q[-6]=0
q[-7]=0
q[-8]=33
oldp[-1]=0
oldp[-2]=0
oldp[-3]=0
oldp[-4]=0
oldp[-5]=0
oldp[-6]=0
oldp[-7]=0
oldp[-8]=33
oldp[0]=0
oldp[1]=0
oldp[2]=0
oldp[3]=0
oldp[4]=0
oldp[5]=0
oldp[6]=0
oldp[7]=0
oldp[8]=0
oldp[9]=0
oldp[10]=0
oldp[11]=0
oldp[12]=0
oldp[13]=0
oldp[14]=0
oldp[15]=0
oldp[16]=0
oldp[17]=0
oldp[18]=0
oldp[19]=0
oldp[20]=0
oldp[21]=0
oldp[22]=0
oldp[23]=0
oldp[24]=33
oldp[25]=0
oldp[26]=0
oldp[27]=0
oldp[28]=0
oldp[29]=0
oldp[30]=0
oldp[31]=0
oldp[32]=0
oldp[33]=64
oldp[34]=107
oldp[35]=0
oldp[36]=0
oldp[37]=0
oldp[38]=0
oldp[39]=0
oldp[40]=0
oldp[41]=0
oldp[42]=0
oldp[43]=0
oldp[44]=0
oldp[45]=0
oldp[46]=0
oldp[47]=0
oldp[48]=0
oldp[49]=0
oldp[50]=0
oldp[51]=0
oldp[52]=0
oldp[53]=0
oldp[54]=0
oldp[55]=0
oldp[56]=49
oldp[57]=0
oldp[58]=0
oldp[59]=0
oldp[60]=0

... freeing oldp

oldp[-1]=0
oldp[-2]=0
oldp[-3]=0
oldp[-4]=0
oldp[-5]=0
oldp[-6]=0
oldp[-7]=0
oldp[-8]=33
oldp[0]=32
oldp[1]=64
oldp[2]=107
oldp[3]=0
oldp[4]=0
oldp[5]=0
oldp[6]=0
oldp[7]=0
oldp[8]=0
oldp[9]=0
oldp[10]=0
oldp[11]=0
oldp[12]=0
oldp[13]=0
oldp[14]=0
oldp[15]=0
oldp[16]=0
oldp[17]=0
oldp[18]=0
oldp[19]=0
oldp[20]=0
oldp[21]=0
oldp[22]=0
oldp[23]=0
oldp[24]=33
oldp[25]=0
oldp[26]=0
oldp[27]=0
oldp[28]=0
oldp[29]=0
oldp[30]=0
oldp[31]=0
oldp[32]=0
oldp[33]=64
oldp[34]=107
oldp[35]=0
oldp[36]=0
oldp[37]=0
oldp[38]=0
oldp[39]=0
oldp[40]=0
oldp[41]=0
oldp[42]=0
oldp[43]=0
oldp[44]=0
oldp[45]=0
oldp[46]=0
oldp[47]=0
oldp[48]=0
oldp[49]=0
oldp[50]=0
oldp[51]=0
oldp[52]=0
oldp[53]=0
oldp[54]=0
oldp[55]=0
oldp[56]=49
oldp[57]=0
oldp[58]=0
oldp[59]=0
oldp[60]=0
Neanche col man riesco a capirci molto su questo codice, aiuto

7 Risposte

  • Re: Comprensione codice con malloc() ecc..

    Fatta in questo modo la domanda è troppo generica ... cosa non capisci in particolare? Un argomento specifico, una linea di codice ... fornisci maggiori dettagli ...
  • Re: Comprensione codice con malloc() ecc..

    ?
    Negli array l'indice è compreso nell'intervallo [0..N). L'uso di un indice negativo ha comportamento indefinito e il compilatore ha (in teoria) la possibilità di fare quel che vuole.
    Per quanto riguarda la malloc(), l'unica cosa da sapere è che restituisce una zona di memoria contigua con la dimensione voluta, e poi tu dedici (tramite un cast) cosa quella memoria significa per te.
  • Re: Comprensione codice con malloc() ecc..

    ATTENZIONE: la malloc AL CONTRARIO DELLA calloc IN INIZIALIZZA LA MEMORIA ALLOCATA.

    Questo vuol dire che dentro un blocco di memoria allocato con la malloc, ci puo' essere di tutto, NON E' PREVEDIBILE.
    All'inizio del programma probabilmente trovi 0, ma dopo un po' trovi sporcizia.

    Se usi la calloc, la memoria viene sempre inizializzata a azero.

    malloc(N) == calloc(1,N) ma con la memoria inizializzata.

    Regola: per non saper ne leggere, ne scriver, usare SEMPRE la calloc a meno di non sapere gia' che anche la malloc va bene, cioe' che se anche il blocco di memoria non e' stato inizializzato (e quindi non si sa che c'e' dentro) non fa nessuna differenza.
  • Re: Comprensione codice con malloc() ecc..

    Kronos24 ha scritto:


    ...devo capire un nuovo codice e capire perchè da un certo output.
    Ritengo doveroso chiedere per quale motivo "devi capire" il codice riportato. Si tratta di un obbligo didattico? Studi su un manuale? Se sì, quale? Qual è la provenienza di codesto codice?

    Riguardo all'uso (sintatticamente ammesso dai compilatori, ma assolutamente deprecato) di indici negativi in C, si veda invece questa discussione.
  • Re: Comprensione codice con malloc() ecc..

    Eccomi, innanzitutto grazie per le risposte
    Ritengo doveroso chiedere per quale motivo "devi capire" il codice riportato. Si tratta di un obbligo didattico? Studi su un manuale? Se sì, quale? Qual è la provenienza di codesto codice?
    E' parte di un esercitazione di laboratorio di cui ho già fatto il resto. Dovrei capire come funziona questo codice e saper spiegare perchè ha questo comportamento.
    Fatta in questo modo la domanda è troppo generica ... cosa non capisci in particolare? Un argomento specifico, una linea di codice ... fornisci maggiori dettagli ...
    Diciamo che fondamentalmente non capisco come e perchè vengono assegnati i numeri ad alcune celle di memoria. Cioè, dopo che viene eseguita la prima malloc, ad esempio, perchè in p[-8] c'è un 33, in p[24] un 225 ecc...? Non ho nemmeno idea di come scoprirlo.
  • Re: Comprensione codice con malloc() ecc..

    Non lo puoi fare/non si puo' fare.
    E' al di fuori del tuo controllo!

    E' come chiedere: ma perche' il sasso su cui sono inciampato, stava proprio li?

    Comunque, una risposta esiste, ed e' la seguente: ha a che fare con gli algoritmi di gestione/allocazione della memoria del processo.

    Ci sono due livelli di allocazione:

    1) quando il programma chiede un blocco di memoria al gestore di memoria (cioe' agli algoritmi su cui la malloc e' implementata), questa viene allocata da quella assegnata al processo.

    2) se non c'e' ne abbastanza, il processo chiede al S.O un nuovo blocco di memoria abbastanza grande.

    Questo perche' non sarebbe efficiente, a livello di sistema operativo, gestire tutte le microscopice allocazioni fatte da tutti i programmi. Quindi il SO assegna blocchi al processo, ed il processo suddivide i blocchi in blocchettini piu' piccoli che poi usa.

    Questo e' anche comodo perche' cosi quando il processo termina (o schianta), il SO sa quali sono i blocchi di memoria assegnati e li ricupera.

    Come viene fatta tutta questa gestione?

    E' abbastanza complicato: tieni presente che il gestore della memoria NON DEVE solo ALLOCARE la memoria richiesta, ma anche tenere traccia di quella rilasciata.

    E lo deve fare in un contesto multithreading, ed essendo la memoria unica, deve assicurarsi di non fare pasticci.

    Ma come fa il gestore della memoria, sapere quanta memoria e' stata allocata e che cosa farne quando viene rilasciata?

    Usa delle informazioni memorizzate in TESTA (accessibili usando indici NEGATIVI) ed in CODA (cioe' andando a leggere OLTRE lo spazio che hai allocato) al tuo blocco di memoria appena allocato:
    c'e' l'informazione della dimensione del blocco, di quale e' il blocco successivo, quello precedente, marcatori di validita' del blocco, ecc.

    Quando tu vai a leggere i dati memorizzati AL DI FUORI del blocco che hai allocato, stai semplicemente andando a leggere le informazioni di servizio gestite dal gestore della memoria.

    Quali sono queste informazioni?

    Non sono standard, dipendono TOTALMENTE da come il gestore di memoria e' stato implementato.

    Per poterlo scoprire devi:

    1) ricuperare i sorgenti della malloc/calloc/free del compilatore C che stai usando (esistono sicuramente, comprenderli e' un'altro paio di maniche)
    2) usare un nuovo gestore di memoria, di cui hai i sorgenti (ne esistono molti: jmalloc tcmalloc, dmalloc, ecc.)
    3) implementare un tuo gestore di memoria : cosa che si fa abbastanza spesso quando le performance di quello standard lasciano a desiderare (si, ci sono casi in cui conviene farlo ).

    Ma la storia non e' finita qui'.

    Per il C++ le cose si complicano: l'implementazione della new e della delete e' basata sulla malloc/free, ma il C++ aggiunge ulteriori informazioni relative alla dimensione del vettore (che serve in fase di deallocazione di classi con distruttore, fatta con a delete[]) e chissa che altro.

    Finito? Non ancora: cosa succede se tu

    1) allochi 500 byte, ci scrivi qualcosa dentro
    2) li rilasci
    3) allochi 1000 byte?

    Molto PROBABILMENTE quello che succede e' che nei primi 500 byte del nuovo blocco (che POTREBBE avere lo stesso indirizzo del precedente) trovi esattamente quello che hai scritto al punto 1).

    Nota: PROBABILMENTE/POTREBBE, ma non e' detto!

    Per questo, quando si alloca un blocco di memoria, conviene usare la calloc (cancellazione automatica) oppure inizializzarla a mano, cosi' eviti di considerare validi valori che stanno li per caso.

    La gestione della memoria e' un argomento COMPLICATO, COMPLESSO e ROGNOSO.
    Ci sono N-mila sfaccettature da prendere in considerazione, N-mila algoritmi, N-mila varianti, casi particolari, ecc.

    Se vuoi fare un salto di qualita', allora usa un bel Garbage Collector: ne esiste uno anche per il C/C++

    http://www.hboehm.info/gc


    Nota: se implementi un tuo gestore di memoria, ti tocca usare indici negativi
  • Re: Comprensione codice con malloc() ecc..

    Wow! Grazie mille, mi hai fatto capire un sacco di cose Ora appena posso riguardo il tutto con un ottica diversa, vediamo se riesco a capirci di più.
Devi accedere o registrarti per scrivere nel forum
7 risposte