Qual è il modo corretto di gestire & # 8220; memoria insufficiente & # 8221 ;?

StackOverflow https://stackoverflow.com/questions/1439977

  •  10-07-2019
  •  | 
  •  

Domanda

Di recente, lavoro su un programma di riproduzione video su Windows per un programma TVCC. Dato che il programma deve decodificare e riprodurre molti video stream contemporaneamente, penso che potrebbe soddisfare la situazione in cui malloc fallirà e aggiungo il controllo dopo ogni malloc.

Ma parlando in termini generali, in questo codice di programmi open source che ho letto in progetti open source, raramente trovo alcun controllo del risultato di malloc. Quindi quando malloc fallisce, la maggior parte dei programmi si blocca. Non è inaccettabile?

I miei colleghi che scrivono programmi server su Linux assegneranno una memoria sufficiente per 100 connessioni client. Quindi anche se il suo programma potrebbe rifiutare il client 101, non incontrerà mai un fallimento di malloc. Il suo approccio è adatto anche per applicazioni desktop?

È stato utile?

Soluzione

Su Linux, malloc () non fallirà mai - invece, il killer OOM verrà attivato e inizierà ad uccidere processi casuali fino a quando il sistema cadrà. Poiché Linux è il derivato UNIX più popolare in uso oggi, molti sviluppatori hanno imparato a non controllare mai il risultato di malloc () . Questo è probabilmente il motivo per cui i tuoi colleghi ignorano gli errori malloc () .

Su sistemi operativi che supportano errori, ho visto due schemi generali:

  • Scrivi una procedura personalizzata che controlla il risultato di malloc () e chiama abort () se l'allocazione fallisce. Ad esempio, le GLib e GTK + utilizzano questo approccio.

  • Memorizza un elenco globale di "quotabile in grado di eliminare" allocazioni, come le cache, che possono essere cancellate in caso di errore di allocazione. Quindi, riprovare a assegnare l'allocazione e, in caso contrario, segnalarla tramite i meccanismi standard di segnalazione degli errori (che non eseguono l'allocazione dinamica).

Altri suggerimenti

Segui l'API standardizzata

Anche su Linux, ulimit può essere usato per ottenere un ritorno all'errore malloc. È solo che il valore predefinito è illimitato.

Esiste una pressione definita per conformarsi agli standard pubblicati. Sulla maggior parte dei sistemi, a lungo termine, e infine anche su Linux, malloc (3) restituirà una corretta indicazione di errore. È vero che i sistemi desktop dispongono di memoria virtuale e richiedono il paging, ma anche in questo caso non controllano malloc ( 3) funziona solo in un programma di debug senza perdite di memoria. Se qualcosa va storto, qualcuno vorrà impostare un ulimit e rintracciarlo. Improvvisamente, il controllo malloc ha un senso.

Usare il risultato di malloc senza controllare null è inaccettabile nel codice che potrebbe essere aperto all'uso su piattaforme in cui malloc può fallire, su quelle che tenderanno a provocare arresti anomali e comportamenti imprevedibili. Non posso prevedere il futuro, non so dove andrà il mio codice, quindi scrivo il codice con i controlli per malloc che restituisce null - meglio morire che comportarsi in modo imprevedibile!

Le strategie su cosa fare in caso di fallimento di malloc dipendono dal tipo di applciazione e da quanta fiducia hai nelle librerie che stai utilizzando. In alcune situazioni l'unica cosa sicura da fare è arrestare l'intero programma.

L'idea di preallocare una quota nota di memoria e di lottizzare in alcuni blocchi, quindi evitare di esaurire effettivamente la memoria è buona, se l'utilizzo della memoria dell'applicazione è prevedibile. Puoi estenderlo a scrivere le tue routine di gestione della memoria per l'uso con il tuo codice.

Dipende dal tipo di applicazione su cui stai lavorando. Se l'applicazione funziona che è divisa in attività discrete in cui una singola attività può fallire, il controllo delle allocazioni di memoria può essere recuperato con garbo.

Ma in molti casi, l'unico modo ragionevole per rispondere a un errore malloc è terminare il programma. Consentire al tuo codice di arrestarsi in modo anomalo sull'inevitabile dereferenza null ci riuscirà. Sarebbe sicuramente sempre meglio scaricare una voce di registro o un messaggio di errore che spiegasse l'errore, ma nel mondo reale lavoriamo su programmi limitati. A volte il ritorno sugli investimenti della gestione degli errori pedanti non è presente.

Controlla sempre e pre-alloca un buffer che può essere liberato in questo caso in modo da poter avvisare l'utente di salvare i suoi dati e chiudere l'applicazione.

Dipende dall'app che scrivi. Ovviamente devi sempre controllare il valore di ritorno di malloc (). Tuttavia, gestire OOM con garbo ha senso solo in molti casi, come i servizi di sistema cruciali di basso livello o quando si scrive una libreria che potrebbe essere utilizzata. Avere un wrapper malloc che si interrompe su OOM è quindi molto comune in molte app e framework. Spesso questi wrapper sono chiamati xmalloc () o simili.

Anche G_malloc () di GLib si sta interrompendo.

Se hai intenzione di gestire enormi quantità di memoria e vuoi fare dichiarazioni su Linux come "ora ho l'area di memoria ABC e non ho bisogno del pezzo B, fai come desideri", dai un'occhiata a Famiglia di funzioni mmap () / madvise () disponibile nella libreria GNU C di serie. A seconda dei modelli di utilizzo, il codice può risultare ancora più semplice rispetto all'utilizzo di malloc. Questa API può anche essere utilizzata per aiutare Linux a non sprecare memoria memorizzando nella cache i file che stai per leggere / scrivere una sola volta.

Sono ben documentati nella documentazione delle informazioni libc di GNU.

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