Se si sa esattamente quanto spazio è necessario mettere da parte e la vostra preoccupazione principale è la prestazione rispetto alla gestione della memoria e il codice non ha bisogno di essere ri-concorrente, allora si vuole allocare oggetti con durata di memorizzazione statica, dichiarandoli nell'ambito del file o utilizzando lo specificatore della classe di memoria static
.
int data[SOME_NUMBER];
void foo(/* some list of parameters here */)
{
static int some_more_data[SOME_OTHER_NUMBER];
...
}
Sia data
e some_more_data
esistono per tutta la durata del programma, ma some_more_data
è visibile solo all'interno della funzione foo
.
In pratica, gli elementi con durata di archiviazione statica hanno spazio riservato per loro nell'immagine binaria stessa, in modo che la memoria sia disponibile non appena il programma viene caricato. Questo può avere un vantaggio per quanto riguarda la località; se i dati e il codice si trovano nella stessa pagina, non è necessario scambiare. Certo, dipende dal codice.
Lo svantaggio ovvio è che il file eseguibile avrà un ingombro maggiore. Un altro inconveniente è che il tuo codice non è re-entrant; ogni chiamata di foo
sta funzionando sullo stesso blocco di memoria quando legge o scrive some_more_data
. A seconda di cosa fa il tuo codice, potrebbe essere o non essere un grosso problema.
Se il codice deve essere rientranti, non è possibile utilizzare oggetti con durata di archiviazione statica. Se il blocco di dati è relativamente piccolo, utilizzare oggetti con durata di archiviazione automatica (ad esempio, variabili locali regolari).
void foo(/* some list of parameters here */)
{
int some_more_data[SOME_SMALLISH_NUMBER];
...
}
In questo caso, some_more_data
esiste solo per la durata della funzione foo
; ogni volta che si chiama foo
, si assegna automaticamente un altro oggetto . Qualsiasi cosa ci sia in testa nel mettere da parte la memoria fa parte del sovraccarico di chiamare la funzione in primo luogo (almeno nella mia esperienza). Il puntatore allo stack viene comunque aggiustato indipendentemente dal fatto che si stiano utilizzando variabili locali oppure no, quindi l'uso di variabili locali non lo renderà più lento. Il problema principale è che la memoria disponibile per gli oggetti automatici è relativamente piccola; per gli oggetti sopra una certa dimensione, questo approccio semplicemente non funzionerà.
Se il codice deve essere rientrante e è necessario allocare grandi blocchi di memoria, sei praticamente bloccato con la gestione della memoria dinamica (malloc/calloc/realloc
e free
). A seconda di come si progetta il codice, è possibile ridurre alcuni dei problemi di prestazioni.
1. Le regole di visibilità vengono applicate durante la conversione dal codice sorgente al codice macchina; in realtà non si applicano in fase di esecuzione.
Sono due "costi" completamente diversi. L'allocazione statica è "gratuita" in termini di tempo di esecuzione, mentre la memoria consuma saggiamente se non utilizzata.La dinamica è ottimale in termini di utilizzo della memoria (di nuovo, se usato con saggezza), ma costa un po 'di tempo di overhead del processore. –
Anche l'allocazione statica presenta un limite di dimensioni molto inferiore rispetto all'allocazione dinamica. –
Non dovrebbe davvero fare alcuna differenza. La memoria deve essere allocata in entrambi i modi, è solo questione se il linker/loader del sistema operativo lo fa o il tuo programma lo fa. Se * può * essere fatto dal caricatore, per definizione è un costo fuori dal giro e assolutamente irrilevante. –