PDA

Visualizza la versione completa : [C++] Controllo allocazione automatica della memoria


GliderKite
07-01-2011, 16:21
Quando avviene precisamente l'allocazione automatica della memoria?

Partendo dal presupposto che entrando in un blocco di istruzioni del tipo:



{
int a = 0;
}


la variabile locale a viene automaticamente allocata sullo stack quando si entra in quel blocco di codice, e distrutta quando si esce dal blocco stesso.

Avevo la necessità di poter controllare l'allocazione automatica della memoria in modo ad esempio di evitare cose del tipo:


int array[ 0xFFFFFF ];

Che produrrebbero necessariamente uno stack overflow runtime non appena si entrerebbe nel blocco di istruzioni in cui viene dichiarato l'array.

Magari anche avere la possibilità di generare un warning se l'allocazione automatica della memoria in un determinato blocco supera un certo valore.

Come fare?

shodan
07-01-2011, 17:11
Non credo si possa fare niente (o almeno non ho mai letto niente in proposito).
Lo spazio riservato alle variabili automatiche è calcolato dal compilatore quando genera il codice.
Diverso il discorso se invece parliamo di allocazione dinamica.
Tra l'altro lo standard C++0x prevede la classe std::array che non prevede nessun controllo sulla dimensione dell'array sottostante. Presumo che se ci fosse stato un modo, lo avrebbero previsto.

GliderKite
07-01-2011, 17:26
Infatti la domanda mi è sorta proprio utilizzando boost::array, ho notato che sopra una certa dimensione si produceva uno stack overflow, ho controllato il codice e anche io non ho visto nessun tipo di controllo di questo genere.

Eppure dovrebbe essere possibile fare una coda del genere, in fondo il compilatore conosce il valore della richiesta di memoria per l'allocazione automatica cosi come conosce la quantità di memoria allocata staticamente, se cosi non fosse non si avrebbe ad esempio il seguente messaggio di errore: fatal error C1126: l'allocazione automatica supera 2G

shodan
07-01-2011, 17:36
Forse c'è qualche switch tra le opzioni del compilatore, ma non mi sono mai preoccupato di controllare. Di sicuro non c'è un modo standard dal momento che ogni compilatore (in senso generale) è libero di riservare quanto stack vuole. VC se non ricordo male usa 2MB per default, ma altri ne possono riservare di più o di meno.

GliderKite
07-01-2011, 17:44
Nel caso di boost:array la dimensione allocata automaticamente sullo stack per il vettore è un Expression parameters. In quel caso se si ha una cosa del tipo:




{
boost::array <int, 10> Vect;
}



L'allocazione su stack avviene ancora prima che venga chiamato il costruttore della classe. Non è possibile controllare che il parametro rappresentante la dimensione non superi un determinato valore? Cioè se avessi la mia classe:



template <typename T, std::size_t Size>
class Vettore
{
T Array[ Size ];
};



esiste un qualsiasi modo per poter controllare il parametro Size in modo che se dovesse superare un determinato valore si eviterebbe lo stack overflow?

shodan
07-01-2011, 17:59
Un modo potrebbe essere questo, che genera un errore di compilazione se la dimensione è eccessiva:


template <typename T, std::size_t Size>
class Vettore
{
T Array[ ( Size < 0xFFFF) ? Size : -1 ];
};


Il valore di comparazione puoi adattarlo alle tue esigenze (anche passarlo come parametro al template volendo).



template <typename T, std::size_t Size, std::size_t MAX_SIZE=0xFFFF>
class Vettore
{
T Array[ ( Size < MAX_SIZE) ? Size : -1 ];
};

MItaly
07-01-2011, 18:47
Non è sempre possibile sapere al momento della compilazione se si rischia l'overflow dello stack (pensa alle funzioni ricorsive), senza contare che, se non erro, la dimensione dello stack di default è un'opzione del linker (che la scrive effettivamente nell'header PE) di cui il compilatore non sa nulla. In ogni caso, allocare sullo stack tanta roba è male.

Per inciso, sotto Windows puoi intercettare l'eccezione SEH STATUS_STACK_OVERFLOW, come si vede qui (http://msdn.microsoft.com/en-us/library/wb1s57t5%28v=vs.80%29.aspx).

GliderKite
07-01-2011, 19:02
Originariamente inviato da shodan
Un modo potrebbe essere questo, che genera un errore di compilazione se la dimensione è eccessiva:


Ecco è già un inizio, anche se l'errore sollevato non fa intendere esattamente qual'è il problema.





Originariamente inviato da MItaly
In ogni caso, allocare sullo stack tanta roba è male.


Perchè esattamente?

Quali sarebbero pro e contro dell'allocazione automatica di un array piuttosto che un allocazione dinamica?



Originariamente inviato da MItaly
sotto Windows puoi intercettare l'eccezione SEH STATUS_STACK_OVERFLOW, come si vede qui.


Interessante, potrebbe essere comodo. Sotto Linux?

MItaly
07-01-2011, 19:10
Originariamente inviato da GliderKite
Perchè esattamente?
Perché lo stack è tradizionalmente piccolo, e viene usato giusto come memoria di lavoro. Se allochi tanta roba rischi uno stack overflow.


Quali sarebbero pro e contro dell'allocazione automatica di un array piuttosto che un allocazione dinamica?
I soliti (http://stackoverflow.com/questions/3889450/when-is-malloc-necessary-in-c/3889495#3889495)


Interessante, potrebbe essere comodo. Sotto Linux?
Se non erro non si fa distinzione rispetto ad altri problemi page faults ed è sempre un SIGSEGV. Tuttavia cercare di gestire uno stack overflow con un signal è una pessima idea, dato che il signal handler avrebbe bisogno di uno stack non pieno per essere eseguito. :)

In generale comunque cercare di gestire degli stack overflow non è una buona idea, dato che si è in una situazione di scarsissima memoria di lavoro, per cui qualunque operazione potrebbe fallire.

Puoi spiegare meglio cosa stai cercando di fare?

GliderKite
07-01-2011, 19:17
Originariamente inviato da MItaly
Puoi spiegare meglio cosa stai cercando di fare?

:)

Certamente, sto appunto cercando di gestire uno stack overflow, anzi più precisamente volevo sapere se esisteva un modo per prevenirlo, in particolar modo quando si dichiarano array automatici, come l'esempio che ho fatto sopra:


double vect[ 0xfffffff ];

ps: secondo le risposte del tuo link i boost::array non dovrebbero esistere...

Loading