Pages: [1]   Go Down
Author Topic: memory free... ma siamo sicuri?  (Read 1311 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 1
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao,
ho scritto uno sketch per capire meglio come funziona l'allocazione della memoria, forse non è il modo migliore ma devo inziare da qualche parte, comunque questo è lo sketch

Code:
#include <FreeMemory.h>

#define LEN_VET 1024

byte vet1[LEN_VET];

void setup() {                 
  Serial.begin(19200);
 
  Serial.println(freeMemory());
 
  for(int i=0;i<LEN_VET;i++) {
    vet1[i] = i;
  } 

  Serial.println(freeMemory()); 
  gen();   
  Serial.println(freeMemory());   
}

void loop() {       
//... 
}

void gen()
{
     byte vet2[LEN_VET];
     
     for(int i=0;i<LEN_VET;i++) {
        vet2[i] = i;
        //Serial.print(vet2[i]);
     }
     Serial.println(freeMemory());   
}

il riusltato è

816
816
814
816

dopo l'istanza del primo vettore sono disponibili 816 byte ?
La quantità di memoria anche dopo l'allocazione non cambia (va bhè qui era scontato ma volevo conferma).
La cosa che più non comprendo è che nella funzione gen() alloco di nuovo un vettore pari al primo, e la memoria disponibile in quel momento è di 814  smiley-slim ?!?! ma come ho allocato un array di 1024 e mi occupa solo 2 byte?
Finita la funzione la memoria ritorna al valore di prima.
Qualcuno saprebbe dirmi cosa succede?
ah... dimenticavo è con Arduino uno 

Grazie
Logged

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

vet2 è una "variabile locale"..quando esci dalla funzione che l'ha creata,ossia gen,viene disallocata...
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

vet2 è una "variabile locale"..quando esci dalla funzione che l'ha creata,ossia gen,viene disallocata...
Quoto. Dichiara vet2 globale.
Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

dopo l'istanza del primo vettore sono disponibili 816 byte ?
Nei 2048 byte di SRAM non ci sta solo il vettore di 1024 byte che hai dichiarato ma anche tutte le altre variabili create dal programma (stai usando la seriale, che è una libreria contenuta nel core, poi stai usando la libreria esterna FreeMemory) nonché lo stack del programma.
Logged


Offline Offline
Newbie
*
Karma: 1
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

dopo l'istanza del primo vettore sono disponibili 816 byte ?
Nei 2048 byte di SRAM non ci sta solo il vettore di 1024 byte che hai dichiarato ma anche tutte le altre variabili create dal programma (stai usando la seriale, che è una libreria contenuta nel core, poi stai usando la libreria esterna FreeMemory) nonché lo stack del programma.

Si ok su questo ci siamo. Quello che non capisco è: se io dichiaro vet1 come globale io mi aspetto che sia allocato staticamente ed infatti la freeMemory() mi dice che ho liberi solo 816byte, nel momento in cui io chiamo la funzione nella quale è dichiarato vet2 di 1024byte questo deve essere allocato in memoria e se chiamo la freeMemory() mi dovrebbe dare 0 o comunque dovrebbe bloccarsi ed invece la freeMemory mi dà 814byte, cioè come se avesse allocato solo un puntatore....Perchè?
Logged

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

a occhio direi che il compilatore ignora il vettore2..tieni conto che nelle ottimizzazioni elimina variabili/array e funzioni non utilizzate,può cancellare di brutto i for e tante altre cose...
e te dichiari vettori non utilizzati..
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

a occhio direi che il compilatore ignora il vettore2..tieni conto che nelle ottimizzazioni elimina variabili/array e funzioni non utilizzate,può cancellare di brutto i for e tante altre cose...
e te dichiari vettori non utilizzati..

Si ok ma come vedi nella funzione ho sia scritto nel vettore2 ed anche stampato, e il risultato non cambia. Ma la cosa più assurda è che se il vet2 lo dichiaro di 9000byte ed eseguo tutto funziona come prima! Dove le prende 9000byte?

Altra prova se nella funzione anziché allocare dichiarando il vettore lo vado ad allocare dinamicamente con la malloc tutto funziona seconda la logica.

Code:
#include <FreeMemory.h>

#define LEN_VET 1024
#define LEN_VET2 300

byte vet1[LEN_VET];


void setup() {                 
  Serial.begin(19200);
 
  Serial.println(freeMemory());
 
  for(int i=0;i<LEN_VET;i++) {
    vet1[i] = i;
  } 

  Serial.println(freeMemory()); 
  gen();   
  Serial.println(freeMemory());   
}

// the loop routine runs over and over again forever:
void loop() {        //...
}
void gen()
{
    byte *vet2;
    //byte vet2[LEN_VET2];   
    vet2 = (byte *) malloc(LEN_VET2 * sizeof(byte));
     
           
     for(int i=0;i<LEN_VET2;i++) {
        vet2[i] = 100;
        //Serial.println(vet2[i]);
     }
     Serial.println(freeMemory());
   
   free(vet2); 
}

Risultato:

810
810
504
810

il che è giusto.
Logged

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

due cose:
-te stai dichiarando un vettore,lo riempi e non usi i valori..forse ti sega anche questo(se compilasse con l'opzoine -O3 nn me ne stupirei)
-sulla malloc con 9000 bisogna considerare che a volte può fallire..solitamente in questo caso ritorna NULL..ma se te non fai controlli del tipo puntatoreRitornato!=NULL,potresti andare a scrivere in qlk area di memoria..quindi andresti a scrivere dall'indirizzo 0 in poi..e dato che usi un'architettura harvard,non rischi di sovrascivere il codice,ma solo i dati..quindi non ti pianti subito..
« Last Edit: September 15, 2012, 10:09:01 am by m_ri » Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

due cose:
-te stai dichiarando un vettore,lo riempi e non usi i valori..forse ti sega anche questo(se compilasse con l'opzoine -O3 nn me ne stupirei)
-sulla malloc con 9000 bisogna considerare che a volte può fallire..solitamente in questo caso ritorna NULL..ma se te non fai controlli del tipo puntatoreRitornato!=NULL,potresti andare a scrivere in qlk area di memoria..quindi andresti a scrivere dall'indirizzo 0 in poi..e dato che usi un'architettura harvard,non rischi di sovrascivere il codice,ma solo i dati..quindi non ti pianti subito..

Nel codice che ho postato la print del valore del vettore è commentata ma ho provato anche a stampare il valore quindi ci accedo e lo uso.

Per quanto riguarda l'esempio dei 9000byte non ho usato il codice della malloc ma quello in cui dichiaro il vettore come variabile nella funzione e oltre a scriverci dentro stampo anche i singoli valori, com'è possibile?
Logged

0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10449
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

uhmmm posta il codice della liibreria che usi

la versione base per lo spazio ram è questa:
Code:
int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

questa funzione dovrebbe solo cotare la distanza tra stack e heap, dove l'inizio dello stack viene considerata l'indirizzo di int v.

in realtà all'interno dello heap possono essere presenti blocchi di memoria che sono stati liberati con una free, e che vengono così contati:

Code:
/* Calculates the size of the free list */
int freeListSize() {
  struct __freelist* current;
  int total = 0;

  for (current = __flp; current; current = current->nx) {
    total += 2; /* Add two bytes for the memory block's header  */
    total += (int) current->sz;
  }

  return total;
}

in teoria quando allochi qualcosa con la malloc, dovresti vedere il valore restituito da freeListSize cambiare, ed eventualmente anche quellod di __brkval se nella lista della ram freeata non c'era abbastanza spazio.

Invece per le variabili dichiarate localmente e senza uso di malloc, dovresti vedere l'indirizzo dello stack cambiare.

per capire cosa realmente sta succedendo, ti consiglio di stampare gli indirizzi delle funzioni, degli array e anche delle variabili locali. così capiamo dove sta il problema.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Newbie
*
Karma: 1
Posts: 31
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

uhmmm posta il codice della liibreria che usi

la libreria è questa http://arduino.cc/playground/Code/AvailableMemory

Quote
per capire cosa realmente sta succedendo, ti consiglio di stampare gli indirizzi delle funzioni, degli array e anche delle variabili locali. così capiamo dove sta il problema.

ho fatto cosi e in effetti ho visto che, se il vet2 viene creato come un "normale" vettore il ciclo for(...)  assegna e stampa il vet2, anche se questo supera di gran lunga la memoria disponibile non si fa scrupoli a sovrascrivere gli stessi indirizzi, tutto cambia se alloco memoria al vettore con malloc, perché se supero la memoria disponibile ho un blocco del programma appena parte, diversamente quando ho spazio libero la freeMemory() ritorna i giusti valori.

Ho avuto lo stesso comportamento della malloc chiamando alla fine della funzione free(vet2).

grazie per l'aiuto
Logged

0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10449
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

in teoria il caso della creazione dell'array normale dovrebbe crashare il programma, ed invece la malloc non crasha il programma in se, ma probabilmente lo fa il fatto che usi il valore NULL che ti restituisce come se fosse un vettore.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

come ho già detto prima,dopo aver fatto la malloc controlla il puntatore: se è NULL,stampi "allocazione fallita" ed esci,altrimenti continui..in questo modo non dovrebbe crashare..
Logged

0
Offline Offline
Faraday Member
**
Karma: 45
Posts: 5790
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

x iscrizione
Logged

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Pages: [1]   Go Up
Jump to: