Su Linux il limite di spazio indirizzo corrente può essere utilizzato per limitare artificialmente la quantità di memoria che un processo può utilizzare. È possibile impostare manualmente questo con setrlimit(RLIMIT_AS, ...)
. Questo può anche essere impostato per un'intera shell in bashrc
utilizzando ulimit -v
. Questo può anche essere impostato per l'intero sistema in /etc/security/limits.conf
. Potrebbe esserci anche una voce/proc/sys per questo da qualche parte, non ne sono sicuro.
Se viene raggiunto il limite di spazio degli indirizzi, il processo genererà un file std :: bad_alloc quando si tenta di allocare più memoria. Su un sistema a 64 bit questa può essere una buona "sicurezza" per assicurarsi che una cattiva applicazione o libreria non scappi con la memoria disponibile e fare in modo che il sistema passi a scambiare o smettere di funzionare del tutto. Assicurati che il programma non lo imposti da qualche parte, e assicurati che il resto dell'ambiente non lo abbia impostato. Puoi semplicemente inserire del codice nel bel mezzo del programma da qualche parte per chiamare getrlimit(RLIMIT_AS, ...)
per essere sicuro che non si sia intrufolato da qualche parte.
Una causa forse più comune (a parte la mancanza di memoria, ovviamente) è un caso intero senza segno, in cui un uin32_t o uint64_t viene utilizzato per allocare memoria ma era 0 e ne ha sottratto 1, a un'allocazione di richieste molto grande (in 64 bit che sarebbero molte migliaia di petabyte).
In ogni caso, i metodi migliori per rintracciare questo sono con GDB. Se la tua applicazione non usa affatto delle eccezioni (e quindi non ha affatto dichiarazioni "catch"), puoi abilitare i file core (ulimit -c unlimited
). La prossima volta che il programma si blocca, il sistema operativo genererà un file core e il caricamento in GDB ti darà immediatamente un backtrace che ti mostra dove si è verificato il crash del programma.
Se si dispone di alcuni (ma non molti) luoghi in cui viene utilizzato try e di questi allocazioni errati, oltre a commentarli mentre si esegue il debug di questo problema, è possibile eseguire l'applicazione in GDB e utilizzare il comando catch throw
per fare in modo che GDB si interrompa ogni volta che viene generata un'eccezione. Affinché uno di questi funzioni, non compilare mai con e compilare sempre (anche quando si utilizza -O3
) con -ggdb
.
allocatori personalizzati in uso? – sehe
Non che io sappia o abbia visto. –
bad_alloc viene lanciato solo per l'errore di allocare memoria, anche se come si nota, se il programma esegue qualcosa di indefinito, potrebbe fare qualsiasi cosa, incluso lanciare bad_alloc in qualsiasi momento dopo l'azione indefinita –