È possibile impedire che si blocchino non utilizzandoli. :)
In tutta serietà, non c'è quasi nessun modo sicuro per usare matrici di lunghezza variabile per rendere la vita più facile a meno che non si abbiano forti limiti sulle dimensioni. D'altra parte, è possibile utilizzare in modo condizionale, in modo simile a questo:
char vla_buf[n < 1000 ? n : 1];
char *buf = sizeof vla_buf < n ? malloc(n) : vla_buf;
if (!buf) goto error;
/* ... Do stuff with buf ... */
if (buf != vla_buf) free(buf);
Mentre questo appare come il dolore inutile, si può fare una grande differenza di prestazioni, soprattutto nelle applicazioni filettate dove molte chiamate a malloc
e free
potrebbe causare un conflitto di blocco. (Un vantaggio collaterale notevole di questo trucco è che è possibile supportare i vecchi compilatori senza VLA con la semplice sostituzione [n < 1000 ? n : 1]
con 1000
, ad esempio con una macro.)
Un altro caso oscuro dove i VLA può essere utile è in algoritmi ricorsivi in cui si conosce il il numero totale di voci di array richieste per tutti i livelli di ricorsione è limitato da n
, dove n
è sufficientemente piccolo da essere sicuro che non verrà sovraccaricato dallo stack, ma dove potrebbero esserci fino a n
livelli di ricorsione e livelli individuali che si consumano a n
elementi. Prima di C99, l'unico modo per gestire questo caso senza lo spazio di stack n^2
era utilizzare malloc
. Con gli VLA, puoi risolvere il problema interamente in pila.
Tenete a mente, questi casi in cui i VLA sono davvero utili sono piuttosto dannosi. Normalmente VLA è solo un modo per ingannare te stesso che la gestione della memoria è facile, fino a quando non ottieni le vulnerabilità risultanti (triviali da sfruttare) che hai creato.:-)
Edit: Per domanda iniziale migliore indirizzo di OP:
#define MAX_VLA 10000
int bar(size_t n)
{
int arr[n <= MAX_VLA ? n : 1];
if (sizeof arr/sizeof *arr < n) return ENOMEM;
/* ... */
return 0;
}
fonte
2010-11-11 03:53:13
Il limite può (sistema dipendente, ovviamente) non essere "memoria" ma "dimensione dello stack". E ora la domanda ha più senso per me perché stavo pensando alla tua implementazione "prima" su una scatola dei consumatori ragionevolmente moderna e mi chiedevo * "Cosa sta facendo che ha bisogno di gran parte di un GB?" *. Comunque. Se lo stack ti limita, il "vecchio" modo potrebbe essere migliore. – dmckee
Questo è esattamente il motivo per cui gli VLA non vengono utilizzati più di tanto (un altro è scarso supporto nei compilatori). I VLA C99 semplicemente non sono stabili. – VSG24