2012-06-10 12 views
5

Następujący program zostanie zabity przez jądro po wyczerpaniu się pamięci. Chciałbym wiedzieć, kiedy zmienna globalna powinna zostać przypisana do "ENOMEM".Kiedy należy przypisać errno do 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

Podobnie jak dodatkowe wskazówki. Nie rzucaj zwrotu 'malloc'. Przesyłanie go do 'void *' jest szczególnie dziwne, ponieważ * jest * typem zwracanym. Jeśli czujesz taką potrzebę, prawdopodobnie zapomniałeś dodać "stdlib.h". Następnie nowoczesne kompilatory języka C (i wszystkie z nich są nowoczesne w tym znaczeniu) mają typ Boolean. Dołącz "stdbool.h" i użyj odpowiednio 'bool',' false' i 'true'. –

Odpowiedz

4

Najpierw naprawić swój kernel nie overcommitu:

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

Teraz malloc powinny zachowywać się właściwie.

+0

+1, ta odpowiedź jest poprawna, choć nie wyjaśnia, dlaczego :) Aby dać ci trochę więcej informacji na temat współczesnych systemów Linux, jeśli nie zrobisz tego, co sugeruje R .. Alokacja rezerwuje po prostu zakres adresów wirtualnych dla procesu i nie przypisuje samych stron. Są one naprawdę naprawiane tylko z jądra, kiedy uzyskujesz do nich dostęp po raz pierwszy. –

+0

Nawet przy mojej poprawce jądro nie od razu przydziela strony. Po prostu wyjaśnia, ile osób będzie potrzebnych i upewnia się, że nigdy więcej nie zrobi więcej, niż można (później) zaspokoić. –

+0

To udało się całkowicie zniszczyć moje pudełko CentOS i wymagało restartu:/ –

2

Zdarza się, gdy spróbujesz przydzielić zbyt dużo pamięci naraz.

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

W twoim przypadku zabójca OOM jest w trakcie procesu.

+0

Czy są zasadniczo jakieś różnice między tymi dwoma przykładami? –

+0

Twoja skrada się na granicy, podczas gdy moja całkowicie ją narusza. –

+0

Nie rozumiem dobrze. –

2

myślę errno zostanie ustawiona na ENOMEM:

Makro zdefiniowane w stdio.h. Oto documentation.

#define ENOMEM   12  /* Out of Memory */ 

Po wywołaniu malloc w tym stwierdzeniem:

myblock = (void *) malloc(MEGABYTE);

a funkcja zwraca systemu NULL -Bo jest z pamięcią -.

Znalazłem this SO pytanie bardzo interesujące.

Mam nadzieję, że pomoże!

2

Jak sugeruje "R", problemem jest domyślne zachowanie zarządzania pamięcią systemu Linux, które jest "przesadne". Oznacza to, że jądro twierdzi, że twoja pamięć powiodła się pomyślnie, ale tak naprawdę nie przydziela pamięci dopiero później, gdy próbujesz uzyskać do niej dostęp. Jeśli jądro dowiaduje się, że przydzielono mu zbyt dużo pamięci, to zabija proces z "zabójcą OOM (Out Of Memory)", aby zwolnić trochę pamięci. Sposób, w jaki wybiera proces zabijania, jest skomplikowany, ale jeśli właśnie przydzielono większość pamięci w systemie, prawdopodobnie będzie to proces, który dostanie kulę.

Jeśli uważasz, że to brzmi szalenie, niektórzy ludzie zgodzą się z tobą.

Aby dostać się zachowywać jak można się spodziewać, jako R powiedział:

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

+0

+1 za "jeśli uważasz, że to brzmi szalenie" .. :-) –