Attualmente sto lavorando su un sistema di segnalazione degli errori basato su eccezioni per le app MSVC++ (9.0) di Windows (ad esempio strutture & di tipo ereditarietà, stack di chiamate, segnalazione errori & registrazione e così via).
La mia domanda ora è: come segnalare correttamente & registrare un errore di memoria insufficiente?
Quando si verifica questo errore, ad es. come bad_alloc
lanciato dall'opzione new
, potrebbero non esserci molte "funzioni" non disponibili, principalmente per quanto riguarda l'ulteriore allocazione di memoria. Normalmente, passerei l'eccezione all'applicazione se è stata lanciata in una lib, quindi utilizzando le finestre di messaggio e i file di log degli errori per segnalare e loggare. Un altro modo (principalmente per i servizi) è utilizzare il registro eventi di Windows.
Il problema principale che ho è quello di assemblare un messaggio di errore. Per fornire alcune informazioni di errore, vorrei definire un messaggio di errore statico (potrebbe essere una stringa letterale, una voce migliore in un file di messaggio, quindi utilizzare FormatMessage) e includere alcune informazioni di runtime come uno stack di chiamate.
Le funzioni/metodi necessari per tale uso siaC++/Windows: come segnalare un'eccezione di memoria esaurita (bad_alloc)?
- STL (
std::string, std::stringstream, std::ofstream
) - CRT (
swprintf_s, fwrite
) - o Win32 API (
StackWalk64, MessageBox, FormatMessage, ReportEvent, WriteFile
)
Oltre ad essere documentata sul MSDN, tutti hanno più (Win32) o meno (STL) closed source in Windows, quindi non so come si comportano in caso di problemi di memoria insufficiente.
solo per dimostrare ci potrebbero essere dei problemi, ho scritto una piccola applicazione banale provocando una bad_alloc:
int main()
{
InitErrorReporter();
try
{
for(int i = 0; i < 0xFFFFFFFF; i++)
{
for(int j = 0; j < 0xFFFFFFFF; j++)
{
char* p = new char;
}
}
}catch(bad_alloc& e_b)
{
ReportError(e_b);
}
DeinitErrorReporter();
return 0;
}
Ran due istanze w/o debugger (in config di uscita, VS 2008), ma "non è successo niente ", ovvero nessun codice di errore da ReportEvent o WriteFile utilizzato internamente nella segnalazione degli errori. Quindi, ha lanciato un'istanza con e un debugger e gli ha consentito di provare a segnalare gli errori uno dopo l'altro utilizzando un punto di interruzione nella riga ReportError. Questo ha funzionato bene per l'istanza con il debugger allegato (riportato correttamente & ha registrato l'errore, anche utilizzando LocalAlloc senza problemi)! Ma il taskman ha mostrato uno strano comportamento, in cui c'è molta memoria liberata prima che l'app esca, suppongo quando viene lanciata l'eccezione.
Si prega di prendere in considerazione ci possono essere più di un processo [modifica] e più di un thread [/ modifica] consumano molta memoria, così liberando spazio pre-assegnati heap non è una soluzione sicura per evitare un ambiente di memoria insufficiente per il processo che vuole segnalare l'errore.
Grazie in anticipo!
Hai mai pensato di avere un blocco di memoria prenotato in anticipo che diventerà la fonte di posizionamento allocazioni ogni volta che il sistema entra in una situazione di esaurimento della memoria? Ho sempre usato questo metodo solo per uscire con grazia dall'applicazione, ma i sistemi operativi (OpenSolaris, Linux) fanno qualcosa di simile a dare all'applicazione il tempo necessario per liberare o scambiare allocazioni a bassa priorità e recuperare con garbo – Sniggerfardimungus
Attualmente, Utilizzo dello spazio di stack (le variabili membro dichiarate quando si chiama InitErrorReporter) per fornire i buffer alle funzioni CRT/WinSDK. Ma non so cosa facciano internamente - vedi l'anser di Alex Farber. – dyp
http://stackoverflow.com/questions/1308052/policy-with-catching-stdbad-alloc parla di qualcosa di simile – Chubsdad