Newsgroup: it.comp.lang.c
Titolo: Pseudo allocatore su microcontrollori

Ciao NG,
Stamattina mi è venuta una specie di illuminazione, ovvero
che forse potrei scrivere qualcosa di mezzo tra
un'allocazione statica e una dinamica. Per esempio,
supponendo che mi servano due array di strutture, non
contemporaneamente, potrei allocare staticamente un array
di char e castare i puntatori necessari. Qualcosa come (a
meno di controlli di dimensioni, eccetera):
char  mem [100] ;
float  *arr1;
int    *arr2;
arr1 = (float*)mem ;
/* lo uso poi non mi serve più */
arr2 = (int*)mem ;
/* come sopra */
Il tutto come in subject perché credo proprio che sui
microcontrollori non ci sia né abbia senso l'allocazione
dinamica.
Una cosa del genere è possibile farla o è una zozzeria? E'
scontata la pericolosità del tutto in mancanza di
controlli rigorosi e massima attenzione.
grazie!
Apx.
-- 
Ci sono tre modi con cui gli industriali possono perdere
enormi capitali: le donne, il gioco e gli ingegneri.
Il primo è il più piacevole; il secondo è il più rapido;
il terzo è il più sicuro.


Mai sentito parlare di union ???
union {
  char   mem[100]
  float  arr1;
  int    arr2;
}x;
;-)
A.

 Apx.
Quasi. Devi solo controllare che la memoria "statica" che usi sia
indirizzabile per il tipo di dato sul processore che usi. Nel tuo
esempio il cast a float (per esempio) non è detto che faccia ottenere
un puntatore utilizzabile. Con le strutture soprattutto, occhio a
lasciare il padding che il compilatore sceglie (senza forzare il
"packing"). Oltretutto, se lavori con un micro, al posto di un buffer
statico, c'è anche la possibilità di riservare direttamente un area e
puntarla con un volatile void *, cosa più saggia perché (1) puoi
scegliere un'area fisica specifica (2) compilatore/linker possono
bloccare la suddetta per altri tipi di accesso. Ovviamente se la 1 o
la 2 siano utili dipende sia dal micro sia dai tool che hai a
disposizione.
In generale, se hai sul sistema un allocatore dinamico direi, a naso e
nella maggior parte dei casi, che è un sistema abbastanza potente per
supportare questa funzionalità senza performance penalties
significative e, nel caso che il codice del costruttore non ti
soddisfi, esistono una marea di allocatori per ogni esigenza ;-)
Ciao!

 massima attenzione.
Con le dovute cautele è una cosa che si può fare senza alcun problema.
Se vuoi essere più tranquillo realizza il pseudo allocatore come una 
funzione in cui tieni memoria se l'array è allocato o meno.  Dovrai 
avere 2 funzioni -- alloc() e free().  La prima oltre a ritornare il 
puntatore (meglio se di tipo void*) segnalerà che l'array è in uso, 
mentre la seconda si limiterà a segnalare l'array disponibile.  Se poi 
vuoi complicare puoi mettere controlli per gestire richieste multiple.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   < 
http://giovanni.homelinux.net/
 >

grazie a tutti, come sempre :)


 un puntatore utilizzabile.
Ciao,
mi illumineresti con un esempio? Il metodo di memory mapping descritto 
da Archaeopteryx per tipi di dato semplici č parecchio utilizzato sui 
microcontrollori e l'attenzione al padding, che io ricordi, dovrebbe 
esser posto solo nel caso di tipi di dato complessi (struct/union/...).
PS:
SE ho scritto cose insensate, allora, non ho proprio capito cosa 
intendevi dire e ti chiedo clemenza.
Grazie per l'attenzione. Saluti.

I consigli che ti hanno dato sono validissimi.
Ricordati che in una gestione come la vuoi fare tu rischi di 
sovrascrivere le variabili. In più devi tenere conto del fatto che char 
ha size 1 e float ha size 4.
Io fari una cosa del genere (con relative ottimizzazioni per salvare 
spazino in ram):
char mem[100];
bool mem_allocata[100];
malloc (int size)
{
	verifico se c'è spazio nel buffer e alloco
	setto mem_allocata per N byte utilizzati
	ritorno Nullo se c'è un errore altrimenti ritorno il puntetore
}
Il 15/12/2010 16.57, Archaeopteryx ha scritto:


 Grazie per l'attenzione. Saluti.
Più semplice potrebbe apparire così:
char a[8];
int i, *ip;
ip = (int*)a;
i = *ip; /* U.B. */
Ogni tipo di dato potrebbe avere per i puntatori un suo allineamento
preferenziale o obbligatorio.
Lo standard ti garantisce che se converti a void* e poi nuovamente al
tipo di partenza non avrai problemi, ma questo non vale per la
conversione in tipi diversi, metodo comunemente chiamato "type
punning". (Per fare un esempio, immagina una macchina in cui char, int
e float siano rispettivamente 1,4 e 8 bytes, e che debbano essere
rappresentati in memoria in locazioni il cui indirizzo sia multiplo di
1,4 e 8 bytes. Convertire un float* in char* sarebbe sempre sicuro, ma
l'operazione contraria sarebbe accettabile solo in 7 casi su 8.)
Per curiosità, è da notare che la malloc() ritorna sì void*, ma è
garantita ritornare un puntatore il cui allineamento è buono per ogni
tipo di dati (nel caso di cui sopra, allineata ad 8).
Ciao!


Non un gran che IMHO. A questo punto, visto che occorrerebbe comunque
implementare un algoritmo di fit, varrebbe la pena scrivere (o meglio
cercare e utilizzare) un piccolo allocatore.
Ciao!

 soddisfi, esistono una marea di allocatori per ogni esigenza ;-)
Puoi fare qualche esempio di questa marea?

 attenzione.
Io mi son trovato anni fa con un problema simile al tuo.
Alla fine mi implementai un piccolo stack e le funzioni malloc e free.
Dai un'occhiata a questo: 
http://www.tinyos.net/nest/apps/tinyalloc/
Si tratta di un sistema di allocazione dinamica della memoria fatto per 
un sistema operativo per microcontrollori
-- 
"Never underestimate the bandwidth of a station wagon full of tapes
hurtling down the highway" - Andrew S. Tanenbaum
http://blog.mainardi.me
python -c "print 'bG9ybWF5bmFAZ21haWwuY29t'.decode('base64')"

 [...]
Ciao  Manlio

Grazie!
Mi hai raccontato una cosa che mi era e mi sarebbe sempre sfuggita.

 dinamica.
Ma in quale contesto ti serve una cosa del genere? In genere sui 
microcontrollori riesco facilmente ad evitare l'allocazione 
(pseudo)dinamica facendo solo allocazioni statiche.

 Ciao!
Utilizzando tipi di dato semplici non riesco a riprodurre l'ottavo caso 
(gcc/vs) e la documentazione che ho trovato parla di 'type punning' solo 
relativamente ai tipi complessi :-(


Che io sappia, "type punning" è un termine generico che si riferisce a
tutte quelle pratiche atte ad aggirare il "type system" del linguaggio
usato. Questo dell'allineamento è uno dei tanti problemi a cui puoi
andare incontro dopo una tale forzatura (il maggiore, dopo sicuramente
quello di rendere il codice più difficile da leggere e manutenere).
In concetto sottostanza, IMO, è che il C (e i suoi compilatori) ti
permettono di uscire fuori dal contesto del controllo dei tipi (in
teoria potresti dichiarare tutto char[] e void*), ma rinunci a vari
benefici che lo standard garantisce (in questo caso la sicurezza di
poter effettuare un assegnamento (!!), garanzia che personalmente
preferirei tenermi!).
Ciao!