Domanda

Ho letto su di condizioni di memoria su Linux, e il seguente paragrafo dalle pagine man mi ha fatto pensare:

  

Per impostazione predefinita, Linux segue una strategia di allocazione della memoria ottimista. Ciò significa che quando malloc () restituisce non-NULL non v'è alcuna garanzia che la memoria è realmente disponibile. Questa è una pessima bug. Nel caso in cui si scopre che il sistema è fuori della memoria, uno o più processi saranno uccisi dal OOM assassino infame. [...]

ci Considerando che l'operatore nuova implementazione finirà chiamando malloc ad un certo punto, sono garanzie che il nuovo sarà effettivamente gettare su Linux? Se non ci sono, come si fa a gestire questa situazione di errore apparentemente non rilevabile?

È stato utile?

Soluzione

Dipende; è possibile configurare le impostazioni di overcommit del kernel utilizzando vm.overcommit_memory.

Herb Sutter discusso qualche anno fa come questo comportamento è in realtà non conforme allo standard C ++ :

  

"Su alcuni sistemi operativi, tra cui Linux, in particolare l'allocazione di memoria riesce sempre. Punto. Come può avere successo allocazione sempre, anche quando la memoria richiesta non è realmente disponibile? La ragione è che l'allocazione in sé semplicemente registra una richiesta di la memoria,. sotto le coperte, la memoria (fisica o virtuale) non è effettivamente impegnato nel processo richiedente, con memoria di supporto vero, finché la memoria è effettivamente utilizzato

     

"Si noti che, se nuovi usi direttamente strutture del sistema operativo, quindi nuovo sarà sempre successo, ma qualsiasi codice innocenti in seguito come buf [100] = 'c'; può lanciare o fallire o battuta d'arresto Da un punto di vista standard C ++. , entrambi gli effetti sono non conformi, in quanto lo standard C ++ prevede che se il nuovo non può impegnarsi abbastanza memoria si deve fallire (questo non lo fa), e che il codice come buf [100] = 'c' non dovrebbe generare un'eccezione o in altro modo fallire (questo potrebbe). "

Altri suggerimenti

Non si può gestire la cosa nel vostro software, pura e semplice.

Per la vostra applicazione si riceverà un puntatore perfettamente valido. Una volta che si cercherà di accedervi, verrà generato un errore di pagina nel kernel, il kernel cercherà di allocare una pagina fisica per esso e se non ci riesce ... braccio.

Ma come vedi, tutto questo avviene all'interno del kernel, l'applicazione non può vedere che. Se si tratta di un sistema critico è possibile disattivare l'overcommit alltogether sul sistema.

Credo che il malloc può ancora tornare NULL. Il motivo per cui è che c'è una differenza tra la memoria di sistema disponibile (RAM + swap) e la quantità nello spazio degli indirizzi del processo.

Ad esempio, se chiedete 3GB di memoria da malloc su una Linux x86 standard, sarà sicuramente tornare NULL poiché questo è impossibile data la quantità di memoria dato alle applicazioni dello spazio utente.

Perdonami se sbaglio, ma non sarebbe il tentativo di azzerare la memoria allocata essere sufficiente a garantire che si dispone di ogni singolo byte che avete richiesto? O anche solo scrivendo all'ultimo byte, sarebbe un'eccezione se la memoria non è stato fatto da te giusto?

Se questo è vero, si può solo provare a scrivere fino all'ultimo (e prima?) Byte della memoria e vedere se funziona bene, e se non lo fa si poteva restituire null da malloc.

Sì, c'è una garanzia che nuova finirà per gettare. Indipendentemente overcommit, la quantità di spazio di indirizzi è limitato. Quindi, se si mantiene l'allocazione della memoria, prima o poi si esaurirà lo spazio di indirizzi e di nuovo sarà costretto a gettare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top