2012-06-10 9 views
5

El kernel mata al siguiente programa cuando se agota la memoria. Me gustaría saber cuándo se debe asignar la variable global a "ENOMEM".¿Cuándo se debe asignar errno 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

consejos Así como adicionales. No eche el retorno de 'malloc'. Lanzarlo a 'void *' es particularmente extraño ya que * es * el tipo de devolución. Si sientes la necesidad, probablemente hayas olvidado incluir "stdlib.h". Entonces los compiladores modernos de C (y en Linux todos son modernos en ese sentido) tienen un tipo booleano. Incluya "stdbool.h" y use 'bool',' false' y 'true' apropiadamente. –

Respuesta

4

En primer lugar, fijar su núcleo no overcommit:

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

ahora malloc debe comportarse adecuadamente.

+0

+1, esta respuesta es la correcta, aunque no explica por qué :) Para darle un poco más de información sobre lo que está sucediendo en los sistemas modernos de Linux, si no hace lo que R .. sugiere. Entonces, una asignación solo reserva un rango de direcciones virtuales para el proceso y no asigna las páginas por sí mismas. Estos solo son reclamados realmente por el núcleo cuando accede a ellos por primera vez. –

+0

Incluso con mi solución, el kernel no asigna las páginas directamente. Simplemente explica cuántos se necesitarán y se asegura de nunca comprometer más de lo que puede (más adelante) estar satisfecho. –

+0

Esto logró romper por completo mi caja de CentOS y requirió un reinicio:/ –

2

Ocurre cuando intenta asignar demasiada memoria a la vez.

#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"); 
    } 
} 

En su caso, el OOM killer está llegando al proceso primero.

+0

¿Existen diferencias entre los dos ejemplos esencialmente? –

+0

El tuyo se arrastra en el límite, mientras que el mío lo viola por completo. –

+0

No entiendo bien. –

2

creo errno se establecerá en ENOMEM:

macro definida en stdio.h. Aquí está el documentation.

#define ENOMEM   12  /* Out of Memory */ 

Después de llamar a malloc en esta declaración:

myblock = (void *) malloc(MEGABYTE);

Y la función devuelve NULL -porque sistema está fuera de la memoria -.

Encontré this SO pregunta muy interesante.

Espero que ayude!

2

Como se insinuó "R", el problema es el comportamiento predeterminado de la gestión de memoria de Linux, que es la "sobrecomisión". Esto significa que el kernel pretende asignar su memoria con éxito, pero en realidad no asigna la memoria hasta más tarde cuando intenta acceder a ella. Si el kernel descubre que tiene demasiada memoria, mata un proceso con el "asesino OOM (Out of Memory)" para liberar algo de memoria. La forma en que escoge el proceso para matar es complicado, pero si acaba de asignar la mayor parte de la memoria en el sistema, probablemente sea su proceso el que obtenga la bala.

Si crees que esto suena loco, algunas personas estarían de acuerdo contigo.

para conseguir que se comporta como se esperaba, ya que dicho R:

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

+0

+1 para "si crees que esto suena loco" ... :-) –

Cuestiones relacionadas