Il libro Game Coding Complete, Fourth Edition , capitolo 5 ( Inizializzazione e spegnimento del gioco ), sezione Checking Memory contiene questo interessante esempio di codice:
bool CheckMemory(const DWORDLONG physicalRAMNeeded, const DWORDLONG virtualRAMNeeded)
{
MEMORYSTATUSEX status;
GlobalMemoryStatusEx(&status);
if (status.ullTotalPhys < physicalRAMNeeded)
{
// you don’t have enough physical memory. Tell the player to go get a
// real computer and give this one to his mother.
GCC_ERROR("CheckMemory Failure: Not enough physical memory.");
return false;
}
// Check for enough free memory.
if (status.ullAvailVirtual < virtualRAMNeeded)
{
// you don’t have enough virtual memory available.
// Tell the player to shut down the copy of Visual Studio running in the
// background, or whatever seems to be sucking the memory dry.
GCC_ERROR("CheckMemory Failure: Not enough virtual memory.");
return false;
}
char *buff = GCC_NEW char[virtualRAMNeeded];
if (buff)
{
delete[] buff;
}
else
{
// even though there is enough memory, it isn't available in one
// block, which can be critical for games that manage their own memory
GCC_ERROR("CheckMemory Failure: Not enough contiguous memory.");
return false;
}
}
Questo solleva alcune domande.
La prima parte chiede solo al sistema operativo (Windows) quanta RAM fisica è disponibile. La parte curiosa è la seconda, che alloca un enorme pezzo di memoria e la libera immediatamente:
char *buff = GCC_NEW char[virtualRAMNeeded];
if (buff)
{
delete[] buff;
}
L'autore continua spiegando:
... questa funzione alloca e rilascia immediatamente un enorme blocco di memoria. Ciò ha l'effetto di fare in modo che Windows ripulisca tutti i rifiuti che si sono accumulati nel gestore della memoria e ricontrolla che puoi allocare un blocco contiguo delle dimensioni di cui hai bisogno. Se la chiamata ha esito positivo, hai essenzialmente eseguito l'equivalente di una macchina Zamboni attraverso la memoria del tuo sistema, rendendolo pronto per il tuo gioco per colpire il ghiaccio ...
Ma ho delle riserve su questo.
"Pulizia della spazzatura che si è accumulata nel gestore della memoria?" Veramente? Se il gioco è appena iniziato, non dovrebbero esserci rifiuti?
"Assicurati di poter allocare un blocco contiguo?" Nel caso molto specifico in cui gestirai la memoria da solo, ciò avrebbe un senso, ma tuttavia, se alloci molta memoria a destra della mazza, praticamente rendi impossibile l'esecuzione di qualsiasi altra applicazione il sistema mentre il tuo è acceso.
Inoltre, non è probabile che questo costringa il sistema operativo a impegnare tutta quella memoria, e di conseguenza sfratta molta memoria nello spazio su disco di swap, rallentando molto l'avvio della tua app?
È davvero una buona pratica?
operator new
for nullptr
), se mi permetti dire. La cosa migliore che puoi fare con quel libro è accendere il tuo camino. Allocare e liberare un grande blocco di memoria ovviamente non "pulisce" la memoria.
new
operatore globale di restituire null invece di lanciare bad_alloc
. In caso contrario, sì, questo codice è ancora più insensato: P
operator delete
è necessario accettarlo nullptr
e trattarlo come no-op. Qualsiasi sovraccarico globale che non lo fa è rotto. Ciò significa che è assurdo in entrambi i casi. Proprio come supporre che l'allocazione di un enorme blocco di memoria e il rilascio di esso "magicamente" farà qualcosa di buono. Nella migliore delle ipotesi, non farà alcun danno (molto probabilmente, dal momento che le pagine non sono nemmeno toccate ... altrimenti potrebbe scambiare alcune pagine dal tuo set di lavoro che dovrai ricaricare in seguito).