2012-06-10 7 views
5

Il seguente programma viene ucciso dal kernel quando la memoria è esaurita. Vorrei sapere quando la variabile globale dovrebbe essere assegnata a "ENOMEM".Quando si deve assegnare erroneamente a ENOMEM?

#define MEGABYTE 1024*1024 
#define TRUE 1 
int main(int argc, char *argv[]){ 

    void *myblock = NULL; 
    int count = 0; 

    while(TRUE) 
    { 
      myblock = (void *) malloc(MEGABYTE); 
      if (!myblock) break; 
      memset(myblock,1, MEGABYTE); 
      printf("Currently allocating %d MB\n",++count); 
    } 
    exit(0); 
} 
+3

suggerimenti Proprio come aggiuntivi. Non eseguire il ritorno di 'malloc'. Lanciarlo a 'void *' è particolarmente strano dal momento che * è * il tipo di ritorno. Se ne senti il ​​bisogno, probabilmente hai dimenticato di includere "stdlib.h". Quindi i compilatori C moderni (e su Linux tutti sono moderni in questo senso) hanno un tipo booleano. Includi "stdbool.h" e usa 'bool',' false' e ​​'true' in modo appropriato. –

risposta

4

In primo luogo, risolvere il tuo kernel non overcommit:

echo "2" > /proc/sys/vm/overcommit_memory 

Ora malloc dovrebbe comportarsi correttamente.

+0

+1, questa risposta è quella corretta, sebbene non spieghi perché :) Per darti un po 'più di informazioni su cosa sta succedendo sui moderni sistemi Linux, se non fai ciò che R .. suggerisce. Un'allocazione quindi riserva solo un intervallo di indirizzi virtuali per il processo e non assegna le pagine stesse. Questi sono realmente reclamati dal kernel quando li si accede per la prima volta. –

+0

Anche con la mia correzione, il kernel non assegna subito le pagine. Rappresenta solo quanti ne saranno necessari e si assicurerà di non impegnarsi mai più di quanto possa (in seguito) essere soddisfatto. –

+0

Questo è riuscito a rompere completamente la mia scatola CentOS e ha richiesto un riavvio:/ –

2

Accade quando si tenta di allocare troppa memoria allo stesso tempo.

#include <stdlib.h> 
#include <stdio.h> 
#include <errno.h> 

int main(int argc, char *argv[]) 
{ 
    void *p; 

    p = malloc(1024L * 1024 * 1024 * 1024); 
    if(p == NULL) 
    { 
    printf("%d\n", errno); 
    perror("malloc"); 
    } 
} 

Nel tuo caso il killer OOM è di arrivare al processo di prima.

+0

Esistono differenze tra i due esempi? –

+0

Il tuo si avvicina al limite, mentre il mio lo viola completamente. –

+0

Non capisco bene. –

2

Penso errno verrà impostato ENOMEM:

Macro definito in stdio.h. Ecco lo documentation.

#define ENOMEM   12  /* Out of Memory */ 

Dopo aver chiamato malloc in questa affermazione:

myblock = (void *) malloc(MEGABYTE);

E la funzione restituisce NULL -perché sistema è la memoria -.

Ho trovato la domanda this SO molto interessante.

Spero che aiuti!

2

Come suggerito da "R", il problema è il comportamento predefinito della gestione della memoria Linux, che è "overcommiting". Ciò significa che il kernel afferma di allocare la memoria con successo, ma in realtà non assegna la memoria più tardi quando si tenta di accedervi. Se il kernel scopre di aver assegnato troppa memoria, uccide un processo con "l'OOM (Out Of Memory) killer" per liberare memoria. Il modo in cui sceglie il processo per uccidere è complicato, ma se hai appena assegnato la maggior parte della memoria nel sistema, probabilmente sarà il tuo processo a ottenere il proiettile.

Se pensi che questo possa sembrare strano, alcune persone sarebbero d'accordo con te.

per farlo comportarsi come ci si aspetta, come diceva R:

echo "2" > /proc/sys/vm/overcommit_memory

+0

+1 per "se pensi che questo suoni pazzesco" .. :-) –

Problemi correlati